﻿using MathNet.Numerics.Distributions;
using Nefarius.ViGEm.Client.Targets.Xbox360;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using PaddleOCRSharp;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Media.Media3D;
using Tesseract;
using static System.Windows.Forms.Cursor;
using static 摸鱼._数据库;
using static 摸鱼._数据库._参数;
using static 摸鱼._数据库._方案;
using static 摸鱼._数据库._方案._步骤;
using static 摸鱼.全局类;
using static 摸鱼.全局类.imageType;
using static 摸鱼.全局类.SendInputs;
using static 摸鱼.图形处理;
using static 摸鱼.核心;
using static 摸鱼.核心._数据;
using static 摸鱼.键鼠.钩子;
using Clipboard = System.Windows.Forms.Clipboard;
using DataFormats = System.Windows.Forms.DataFormats;
using Font = System.Drawing.Font;
using FontStyle = System.Drawing.FontStyle;
using Point = System.Drawing.Point;
using Rectangle = System.Drawing.Rectangle;

namespace 摸鱼
{
    internal static class 方法Action
    {
        [SkipLocalsInit]
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        public static void Do(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            switch (方法.名字)
            {
                case nameof(模板找图): 模板找图(数据, 步骤, 方法, 方法data); break;
                case nameof(取色): 取色(数据, 步骤, 方法, 方法data); break;
                case nameof(特征匹配): 特征匹配(数据, 步骤, 方法, 方法data); break;
                case nameof(找单色): 找单色(数据, 步骤, 方法, 方法data); break;
                case nameof(找色块): 找色块(数据, 步骤, 方法, 方法data); break;
                case nameof(SVM二分类训练): SVM二分类训练(数据, 步骤, 方法, 方法data); break;
                case nameof(SVM二分类检测): SVM二分类检测(数据, 步骤, 方法, 方法data); break;
                case nameof(图片录制拼接): 图片录制拼接(数据, 步骤, 方法, 方法data); break;
                case nameof(误差验证): 误差验证(数据, 步骤, 方法, 方法data); break;
                case nameof(距离计算): 距离计算(数据, 步骤, 方法, 方法data); break;
                case nameof(获取鼠标特征码): 获取鼠标特征码(数据, 步骤, 方法, 方法data); break;
                case nameof(左击): 左击(数据, 步骤, 方法, 方法data); break;
                case nameof(右击): 右击(数据, 步骤, 方法, 方法data); break;
                case nameof(滚轮滑动): 滚轮滑动(数据, 步骤, 方法, 方法data); break;
                case nameof(直线移动): 直线移动(数据, 步骤, 方法, 方法data); break;
                case nameof(人类鼠标移动): 人类鼠标移动(数据, 步骤, 方法, 方法data); break;
                case nameof(等待): 等待(数据, 步骤, 方法, 方法data); break;
                case nameof(等待_偏态分布): 等待_偏态分布(数据, 步骤, 方法, 方法data); break;
                case nameof(判断): 判断(数据, 步骤, 方法, 方法data); break;
                case nameof(循环): 循环(数据, 步骤, 方法, 方法data); break;
                case nameof(播放): 播放(数据, 步骤, 方法, 方法data); break;
                case nameof(代码): 代码(数据, 步骤, 方法, 方法data); break;
                case nameof(相对移动1): 相对移动1(数据, 步骤, 方法, 方法data); break;
                case nameof(相对移动2): 相对移动2(数据, 步骤, 方法, 方法data); break;
                case nameof(相对移动3): 相对移动3(数据, 步骤, 方法, 方法data); break;
                case nameof(获取位置): 获取位置(数据, 步骤, 方法, 方法data); break;
                case nameof(屏蔽键鼠): 屏蔽键鼠(数据, 步骤, 方法, 方法data); break;
                case nameof(屏蔽移动): 屏蔽移动(数据, 步骤, 方法, 方法data); break;
                case nameof(屏蔽): 屏蔽(数据, 步骤, 方法, 方法data); break;
                case nameof(跳转步骤): 跳转步骤(数据, 步骤, 方法, 方法data); break;
                case nameof(执行步骤): 执行步骤(数据, 步骤, 方法, 方法data); break;
                case nameof(执行多步骤): 执行多步骤(数据, 步骤, 方法, 方法data); break;
                case nameof(结束步骤): 结束步骤(数据, 步骤, 方法, 方法data); break;
                case nameof(结束方案): 结束方案(数据, 步骤, 方法, 方法data); break;
                case nameof(获取窗口句柄): 获取窗口句柄(数据, 步骤, 方法, 方法data); break;
                case nameof(获取窗口主句柄): 获取窗口主句柄(数据, 步骤, 方法, 方法data); break;
                case nameof(获取当前窗口主句柄): 获取当前窗口主句柄(数据, 步骤, 方法, 方法data); break;
                case nameof(跳转并结束): 跳转并结束(数据, 步骤, 方法, 方法data); break;
                case nameof(注册键盘钩子): 注册键盘钩子(数据, 步骤, 方法, 方法data); break;
                case nameof(注册键盘钩子a): 注册键盘钩子a(数据, 步骤, 方法, 方法data); break;
                case nameof(注册鼠标钩子): 注册鼠标钩子(数据, 步骤, 方法, 方法data); break;
                case nameof(注册鼠标钩子a): 注册鼠标钩子a(数据, 步骤, 方法, 方法data); break;
                case nameof(键盘同步鼠标): 键盘同步鼠标(数据, 步骤, 方法, 方法data); break;
                case nameof(键盘同步键盘): 键盘同步键盘(数据, 步骤, 方法, 方法data); break;
                case nameof(按下判断): 按下判断(数据, 步骤, 方法, 方法data); break;
                case nameof(弹起判断): 弹起判断(数据, 步骤, 方法, 方法data); break;
                case nameof(鼠标按下判断): 鼠标按下判断(数据, 步骤, 方法, 方法data); break;
                case nameof(鼠标弹起判断): 鼠标弹起判断(数据, 步骤, 方法, 方法data); break;
                case nameof(创建按钮): 创建按钮(数据, 步骤, 方法, 方法data); break;
                case nameof(创建按钮a): 创建按钮a(数据, 步骤, 方法, 方法data); break;
                case nameof(创建标签): 创建标签(数据, 步骤, 方法, 方法data); break;
                case nameof(异步调用方案): 异步调用方案(数据, 步骤, 方法, 方法data); break;
                case nameof(同步调用方案): 同步调用方案(数据, 步骤, 方法, 方法data); break;
                case nameof(获取时间戳): 获取时间戳(数据, 步骤, 方法, 方法data); break;
                case nameof(位置回溯): 位置回溯(数据, 步骤, 方法, 方法data); break;
                case nameof(传播消息): 传播消息(数据, 步骤, 方法, 方法data); break;
                case nameof(订阅消息): 订阅消息(数据, 步骤, 方法, 方法data); break;
                case nameof(订阅变量): 订阅变量(数据, 步骤, 方法, 方法data); break;
                case nameof(复制变量值): 复制变量值(数据, 步骤, 方法, 方法data); break;
                case nameof(暂停其他方案): 暂停其他方案(数据, 步骤, 方法, 方法data); break;
                case nameof(训练): 训练(数据, 步骤, 方法, 方法data); break;
                case nameof(目标检测): 目标检测(数据, 步骤, 方法, 方法data); break;
                case nameof(获取长度): 获取长度(数据, 步骤, 方法, 方法data); break;
                case nameof(添加元素): 添加元素(数据, 步骤, 方法, 方法data); break;
                case nameof(插入元素): 插入元素(数据, 步骤, 方法, 方法data); break;
                case nameof(删除元素): 删除元素(数据, 步骤, 方法, 方法data); break;
                case nameof(删除索引): 删除索引(数据, 步骤, 方法, 方法data); break;
                case nameof(替换元素): 替换元素(数据, 步骤, 方法, 方法data); break;
                case nameof(替换索引): 替换索引(数据, 步骤, 方法, 方法data); break;
                case nameof(遍历读取): 遍历读取(数据, 步骤, 方法, 方法data); break;
                case nameof(遍历写入): 遍历写入(数据, 步骤, 方法, 方法data); break;
                case nameof(原地左击): 原地左击(数据, 步骤, 方法, 方法data); break;
                case nameof(原地右击): 原地右击(数据, 步骤, 方法, 方法data); break;
                case nameof(获取剪切板内容): 获取剪切板内容(数据, 步骤, 方法, 方法data); break;
                case nameof(包含文字): 包含文字(数据, 步骤, 方法, 方法data); break;
                case nameof(截取文字): 截取文字(数据, 步骤, 方法, 方法data); break;
                case nameof(替换文字): 替换文字(数据, 步骤, 方法, 方法data); break;
                case nameof(插入文字): 插入文字(数据, 步骤, 方法, 方法data); break;
                case nameof(删除文字): 删除文字(数据, 步骤, 方法, 方法data); break;
                case nameof(获取文字位置): 获取文字位置(数据, 步骤, 方法, 方法data); break;
                case nameof(读取文本文件): 读取文本文件(数据, 步骤, 方法, 方法data); break;
                case nameof(屏蔽步骤): 屏蔽步骤(数据, 步骤, 方法, 方法data); break;
                case nameof(屏蔽步骤a): 屏蔽步骤a(数据, 步骤, 方法, 方法data); break;
                case nameof(重排步骤并执行): 重排步骤并执行(数据, 步骤, 方法, 方法data); break;
                case nameof(切换窗口): 切换窗口(数据, 步骤, 方法, 方法data); break;
                case nameof(左击a): 左击a(数据, 步骤, 方法, 方法data); break;
                case nameof(右击a): 右击a(数据, 步骤, 方法, 方法data); break;
                case nameof(截图): 截图(数据, 步骤, 方法, 方法data); break;
                case nameof(定时a): 定时a(数据, 步骤, 方法, 方法data); break;
                case nameof(定时b): 定时b(数据, 步骤, 方法, 方法data); break;
                case nameof(时间计划): 时间计划(数据, 步骤, 方法, 方法data); break;
                case nameof(时长统计): 时长统计(数据, 步骤, 方法, 方法data); break;
                case nameof(画圆): 画圆(数据, 步骤, 方法, 方法data); break;
                case nameof(异步方法): 异步方法(数据, 步骤, 方法, 方法data); break;
                case nameof(时间拦截): 时间拦截(数据, 步骤, 方法, 方法data); break;
                case nameof(时间筛查): 时间筛查(数据, 步骤, 方法, 方法data); break;
                case nameof(预约方法): 预约方法(数据, 步骤, 方法, 方法data); break;
                case nameof(返回父级): 返回父级(数据, 步骤, 方法, 方法data); break;
                case nameof(跳过父级以及后续方法): 跳过父级以及后续方法(数据, 步骤, 方法, 方法data); break;
                case nameof(循环a): 循环a(数据, 步骤, 方法, 方法data); break;
                case nameof(限时循环): 限时循环(数据, 步骤, 方法, 方法data); break;
                case nameof(执行父方法): 执行父方法(数据, 步骤, 方法, 方法data); break;
                case nameof(窗口镜像): 窗口镜像(数据, 步骤, 方法, 方法data); break;
                case nameof(ch_OCR): ch_OCR(数据, 步骤, 方法, 方法data); break;
                case nameof(ch_OCR_a): ch_OCR_a(数据, 步骤, 方法, 方法data); break;
                case nameof(en_OCR): en_OCR(数据, 步骤, 方法, 方法data); break;
                case nameof(en_OCR_a): en_OCR_a(数据, 步骤, 方法, 方法data); break;
                case nameof(提取数字): 提取数字(数据, 步骤, 方法, 方法data); break;
                case nameof(提取数字a): 提取数字a(数据, 步骤, 方法, 方法data); break;
                case nameof(提取数字b): 提取数字b(数据, 步骤, 方法, 方法data); break;
                case nameof(提取数字c): 提取数字c(数据, 步骤, 方法, 方法data); break;
                case nameof(四舍五入): 四舍五入(数据, 步骤, 方法, 方法data); break;
                case nameof(向上取整): 向上取整(数据, 步骤, 方法, 方法data); break;
                case nameof(向下取整): 向下取整(数据, 步骤, 方法, 方法data); break;
                case nameof(保留整数): 保留整数(数据, 步骤, 方法, 方法data); break;
                case nameof(变化监控): 变化监控(数据, 步骤, 方法, 方法data); break;
                case nameof(按住按键): 按住按键(数据, 步骤, 方法, 方法data); break;
                case nameof(弹起按键): 弹起按键(数据, 步骤, 方法, 方法data); break;
                case nameof(弹起鼠标按键): 弹起鼠标按键(数据, 步骤, 方法, 方法data); break;
                case nameof(按住鼠标按键): 按住鼠标按键(数据, 步骤, 方法, 方法data); break;
                case nameof(命令行): 命令行(数据, 步骤, 方法, 方法data); break;
                case nameof(注销手柄): 注销手柄(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄A键): 手柄A键(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄B键): 手柄B键(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄X键): 手柄X键(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄Y键): 手柄Y键(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄Up键): 手柄Up键(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄Down键): 手柄Down键(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄Left键): 手柄Left键(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄Right键): 手柄Right键(数据, 步骤, 方法, 方法data); break;
                case nameof(手柄Back键): 手柄Back键(数据, 步骤, 方法, 方法data); break;
                case nameof(Start): Start(数据, 步骤, 方法, 方法data); break;
                case nameof(LS): LS(数据, 步骤, 方法, 方法data); break;
                case nameof(RS): RS(数据, 步骤, 方法, 方法data); break;
                case nameof(LB): LB(数据, 步骤, 方法, 方法data); break;
                case nameof(RB): RB(数据, 步骤, 方法, 方法data); break;
                case nameof(LT): LT(数据, 步骤, 方法, 方法data); break;
                case nameof(RT): RT(数据, 步骤, 方法, 方法data); break;
                case nameof(Guide): Guide(数据, 步骤, 方法, 方法data); break;
                case nameof(左摇杆X轴): 左摇杆X轴(数据, 步骤, 方法, 方法data); break;
                case nameof(左摇杆Y轴): 左摇杆Y轴(数据, 步骤, 方法, 方法data); break;
                case nameof(右摇杆X轴): 右摇杆X轴(数据, 步骤, 方法, 方法data); break;
                case nameof(右摇杆Y轴): 右摇杆Y轴(数据, 步骤, 方法, 方法data); break;
                default:
                    组合键拆解(数据, 步骤, 方法, 方法data); break;
            }
        }
        //123
        public static void 初始化()
        {
            锁定 = false;
        }
        public static void Dispose()
        {
            手柄?.Dispose();
        }




        private static void 命令行(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            // 构造命令行指令
            string command = 方法.参数[CS.代码].值;

            // 创建ProcessStartInfo对象
            ProcessStartInfo processStartInfo = new()
            {
                FileName = "cmd.exe", // 指定命令行程序
                Arguments = $"/c {command}", // 执行的命令
                RedirectStandardOutput = true, // 重定向标准输出
                //UseShellExecute = false, // 不使用系统外壳程序启动
                //CreateNoWindow = true // 不显示窗口
            };

            // 启动进程
            Process process = Process.Start(processStartInfo);
        }
        private static void 提取数字(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string 内容 = 方法.参数[CS.变量1].变量值;
            string 变量 = 方法.参数[CS.变量2].值;
            bool 忽略小逗号 = 方法.参数[CS.布尔值][valueType.Bool];
            bool 忽略大逗号 = 方法.参数[CS.布尔值2][valueType.Bool];
            StringBuilder stringBuilder = new(内容.Length);

            int i = 0;
            int 连续符 = 0;
            foreach (var item in 内容)
            {
                if (char.IsDigit(item))
                {
                    stringBuilder.Append(item);
                    连续符 = 0;
                }
                else if (item == '.')
                {
                    if (连续符 == 0)
                        stringBuilder.Append(item);
                    连续符++;
                }
                else if (item == ',' && 忽略小逗号)
                    continue;
                else if (item == '，' && 忽略大逗号)
                    continue;
                else if (i != 0)
                    break;
                i++;
            }

            for (int j = 0; j < stringBuilder.Length; j++)
            {
                if (stringBuilder[j] == '.')
                    stringBuilder.Remove(j, 1);
                else
                    break;
            }
            for (int j = stringBuilder.Length - 1; j > -1; j--)
            {
                if (stringBuilder[j] == '.')
                    stringBuilder.Remove(j, 1);
                else
                    break;
            }

            变量.赋值(stringBuilder.ToString());
        }
        private static void 提取数字a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string 内容 = 方法.参数[CS.变量1].变量值;
            string 变量 = 方法.参数[CS.变量2].值;
            StringBuilder stringBuilder = new(内容.Length);

            int 连续符 = 0;
            foreach (var item in 内容)
                if (char.IsDigit(item))
                {
                    stringBuilder.Append(item);
                    连续符 = 0;
                }
                else if (item == '.')
                {
                    if (连续符 == 0)
                        stringBuilder.Append(item);
                    连续符++;
                }

            for (int j = 0; j < stringBuilder.Length; j++)
            {
                if (stringBuilder[j] == '.')
                    stringBuilder.Remove(j, 1);
                else
                    break;
            }
            for (int j = stringBuilder.Length - 1; j > -1; j--)
            {
                if (stringBuilder[j] == '.')
                    stringBuilder.Remove(j, 1);
                else
                    break;
            }
            变量.赋值(stringBuilder.ToString());
        }
        private static void 提取数字b(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string 内容 = 方法.参数[CS.变量1].变量值;
            string 变量 = 方法.参数[CS.变量2].值;
            char 分隔符 = 方法.参数[CS.文本1].值[0];
            bool 忽略小逗号 = 方法.参数[CS.布尔值][valueType.Bool];
            bool 忽略大逗号 = 方法.参数[CS.布尔值2][valueType.Bool];
            StringBuilder stringBuilder = new(内容.Length);

            int i = 0;
            int 连续符 = 0;
            foreach (var item in 内容)
            {
                if (char.IsDigit(item))
                {
                    stringBuilder.Append(item);
                    连续符 = 0;
                }
                else if (item == '.')
                {
                    if (连续符 == 0)
                        stringBuilder.Append(item);
                    连续符++;
                }
                else if (item == ',' && 忽略小逗号)
                    continue;
                else if (item == '，' && 忽略大逗号)
                    continue;
                else if (item == 分隔符)
                {
                    if (连续符 == 0)
                        stringBuilder.Append(',');
                    连续符++;
                }
                else if (i != 0)
                    break;
                i++;
            }

            for (int j = 0; j < stringBuilder.Length; j++)
            {
                char item = stringBuilder[j];
                if (item == '.' || item == ',')
                    stringBuilder.Remove(j, 1);
                else
                    break;
            }
            for (int j = stringBuilder.Length - 1; j > -1; j--)
            {
                char item = stringBuilder[j];
                if (item == '.' || item == ',')
                    stringBuilder.Remove(j, 1);
                else
                    break;
            }
            变量.赋值(stringBuilder.ToString());
        }
        private static void 提取数字c(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = 方法.参数[CS.变量1].变量值;
            string 变量 = 方法.参数[CS.变量2].值;
            char 分隔符 = 方法.参数[CS.文本1].值[0];
            StringBuilder stringBuilder = new(内容.Length);

            int 连续符 = 0;
            foreach (var item in 内容)
                if (char.IsDigit(item))
                {
                    stringBuilder.Append(item);
                    连续符 = 0;
                }
                else if (item == '.')
                {
                    if (连续符 == 0)
                        stringBuilder.Append(item);
                    连续符++;
                }
                else if (item == 分隔符)
                {
                    if (连续符 == 0)
                        stringBuilder.Append(',');
                    连续符++;
                }

            for (int j = 0; j < stringBuilder.Length; j++)
            {
                char item = stringBuilder[j];
                if (item == '.' || item == ',')
                    stringBuilder.Remove(j, 1);
                else
                    break;
            }
            for (int j = stringBuilder.Length - 1; j > -1; j--)
            {
                char item = stringBuilder[j];
                if (item == '.' || item == ',')
                    stringBuilder.Remove(j, 1);
                else
                    break;
            }
            变量.赋值(stringBuilder.ToString());
        }
        private static void 四舍五入(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            double 变量 = 方法.参数[CS.变量1][valueType.Double];
            方法.参数[CS.变量2].值.赋值(Math.Round(变量, 0).ToString());
        }
        private static void 向上取整(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            double 变量 = 方法.参数[CS.变量1][valueType.Double];
            方法.参数[CS.变量2].值.赋值(Math.Ceiling(变量).ToString());
        }
        private static void 向下取整(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            double 变量 = 方法.参数[CS.变量1][valueType.Double];
            方法.参数[CS.变量2].值.赋值(Math.Floor(变量).ToString());
        }
        private static void 保留整数(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            double 变量 = 方法.参数[CS.变量1][valueType.Double];
            方法.参数[CS.变量2].值.赋值(Math.Truncate(变量).ToString());
        }
        private static PaddleOCREngine ch_OCR_Model;
        private static void ch_OCR(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (ch_OCR_Model == null)
            {
                ch_OCR_aModel?.Dispose();
                en_OCR_aModel?.Dispose();
                OCRParameter oCRParameter = new OCRParameter();
                oCRParameter.cpu_math_library_num_threads = 1;//预测并发线程数
                oCRParameter.cls = false; //是否执行文字方向分类；默认false
                oCRParameter.det = false;//是否开启方向检测，用于检测识别180旋转
                OCRModelConfig config = new()
                {
                    keys = ".\\inference\\ppocr_keys.txt",
                    rec_infer = ".\\inference\\ch_PP-OCRv4_rec_infer",
                    det_infer = ".\\inference\\ch_PP-OCRv4_det_infer",
                    cls_infer = ".\\inference\\ch_ppocr_mobile_v2.0_cls_infer",
                };
                ch_OCR_Model = new PaddleOCRSharp.PaddleOCREngine(config, oCRParameter);
            }
            string 变量 = 方法.参数[CS.变量1].值;
            int[] 区域 = 方法.参数[CS.区域].区域s;
            float 置信度 = 方法.参数[CS.相似度1][valueType.Float];
            var 截图大小 = new OpenCvSharp.Rect(区域[0], 区域[1], (区域[2] - 区域[0]), (区域[3] - 区域[1]));

            Using(new Mat(截屏.图片[0, imageType.Mat], 截图大小), 大图mat =>
            {
                var result = ch_OCR_Model.DetectStructure(大图mat.ToBitmap());
                foreach (var line in result.TextBlocks)
                {
                    if (line.Score > 置信度)
                    {
                        变量.赋值(line.Text);
                        方法data.循环num = 1;
                    }
                    else
                        方法data.循环num = 0;
                }
            });
        }
        private static PaddleOCREngine ch_OCR_aModel;
        private static void ch_OCR_a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (ch_OCR_aModel == null)
            {
                en_OCR_aModel?.Dispose();
                ch_OCR_Model?.Dispose();
                OCRParameter oCRParameter = new OCRParameter();
                oCRParameter.cpu_math_library_num_threads = 1;//预测并发线程数
                oCRParameter.cls = false; //是否执行文字方向分类；默认false
                oCRParameter.det = true;//是否开启区域检测
                OCRModelConfig config = new()
                {
                    keys = ".\\inference\\ppocr_keys.txt",
                    rec_infer = ".\\inference\\ch_PP-OCRv4_rec_infer",
                    det_infer = ".\\inference\\ch_PP-OCRv4_det_infer",
                    cls_infer = ".\\inference\\ch_ppocr_mobile_v2.0_cls_infer",
                };
                ch_OCR_aModel = new PaddleOCRSharp.PaddleOCREngine(config, oCRParameter);
            }
            方法data.循环num = 0;
            string 变量 = 方法.参数[CS.变量1].值;
            int[] 区域 = 方法.参数[CS.区域].区域s;
            float 置信度 = 方法.参数[CS.相似度1][valueType.Float];
            var 截图大小 = new OpenCvSharp.Rect(区域[0], 区域[1], (区域[2] - 区域[0]), (区域[3] - 区域[1]));

            Using(new Mat(截屏.图片[0, imageType.Mat], 截图大小), 大图mat =>
            {
                var result = ch_OCR_aModel.DetectStructure(大图mat.ToBitmap());
                StringBuilder resul = new();
                foreach (var line in result.TextBlocks)
                {
                    if (line.Score > 置信度)
                    {
                        if (resul.Length == 0)
                            resul.Append(line.Text);
                        else
                            resul.Append('\n').Append(line.Text);
                        方法data.循环num = 1;
                    }
                }
                if (resul.Length != 0)
                    变量.赋值(resul.ToString());
            });
        }
        private static PaddleOCREngine en_OCR_aModel;
        private static void en_OCR(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (en_OCR_aModel == null)
            {
                ch_OCR_aModel?.Dispose();
                ch_OCR_Model?.Dispose();
                OCRParameter oCRParameter = new OCRParameter();
                oCRParameter.cpu_math_library_num_threads = 1;//预测并发线程数
                oCRParameter.cls = false; //是否执行文字方向分类；默认false
                oCRParameter.det = true;//是否开启区域检测
                OCRModelConfig config = new()
                {
                    keys = ".\\inference\\en_dict.txt",
                    rec_infer = ".\\inference\\en_PP-OCRv3_rec_slim_infer",
                    det_infer = ".\\inference\\ch_PP-OCRv4_det_infer",
                    cls_infer = ".\\inference\\ch_ppocr_mobile_v2.0_cls_infer",
                };
                en_OCR_aModel = new PaddleOCRSharp.PaddleOCREngine(config, oCRParameter);
            }
            方法data.循环num = 0;
            string 变量 = 方法.参数[CS.变量1].值;
            int[] 区域 = 方法.参数[CS.区域].区域s;
            float 置信度 = 方法.参数[CS.相似度1][valueType.Float];
            var 截图大小 = new OpenCvSharp.Rect(区域[0], 区域[1], (区域[2] - 区域[0]), (区域[3] - 区域[1]));

            Using(new Mat(截屏.图片[0, imageType.Mat], 截图大小), 大图mat =>
            {
                var result = en_OCR_aModel.DetectStructure(大图mat.ToBitmap());
                StringBuilder resul = new();
                foreach (var line in result.TextBlocks)
                {
                    if (line.Score > 置信度)
                    {
                        if (resul.Length == 0)
                            resul.Append(line.Text);
                        else
                            resul.Append('\n').Append(line.Text);
                        方法data.循环num = 1;
                    }
                }
                if (resul.Length != 0)
                    变量.赋值(resul.ToString());
            });
        }
        private static TesseractEngine TesseractE;
        private static void en_OCR_a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (TesseractE == null)
                TesseractE = new TesseractEngine(@"./x64", "eng", EngineMode.TesseractOnly);

            string 变量 = 方法.参数[CS.变量1].值;
            int[] 区域 = 方法.参数[CS.区域].区域s;
            float 置信度 = 方法.参数[CS.相似度1][valueType.Float];
            var 截图大小 = new OpenCvSharp.Rect(区域[0], 区域[1], (区域[2] - 区域[0]), (区域[3] - 区域[1]));

            Using(new Mat(截屏.图片[0, imageType.Mat], 截图大小), 大图mat =>
            {
                using (var result = TesseractE.Process(大图mat.去噪二值化(), PageSegMode.SingleBlock))
                {
                    var Score = result.GetMeanConfidence();
                    if (Score > 置信度)
                    {
                        变量.赋值(result.GetText());
                        方法data.循环num = 1;
                    }
                    else
                        方法data.循环num = 0;
                }
            });
        }
        private static void 窗口镜像(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法data.控件 == null)
            {
                IntPtr 后台窗口句柄 = 方法.参数[CS.窗口句柄][valueType.Int];
                MoyuControl.MsgboxThrow(!Win32.IsWindow(后台窗口句柄), "镜像窗口句柄错误: " + 后台窗口句柄);
                System.Drawing.Point 屏幕位置 = 方法.参数[CS.坐标].坐标;
                Win32.RECT 镜像区域 = 方法.参数[CS.区域].区域win32RECT;
                double 缩放比例 = 方法.参数[CS.数字1][valueType.Double];
                方法data.控件 = new MoyuControl.Form_穿透_置顶(屏幕位置);
                (方法data.控件 as MoyuControl.Form_穿透_置顶).AsyncShow(方法data,
                    () => Win32.Creat镜像窗口(后台窗口句柄, (Form)方法data.控件, 镜像区域, 缩放比例, ref 方法data.Dwm绑定句柄));
                方法data.循环num = 1;
                方法data.循环尾调用 = 1;
            }
            else
            {
                方法data.控件.Invoke(() => 方法data.控件.Visible = !方法data.控件.Visible);
                if (方法data.控件.Visible)
                {
                    方法data.循环num = 1;
                    方法data.循环尾调用 = 1;
                }
            }
        }
        private static void 循环a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => 方法data.循环num = int.MaxValue;
        private static void 执行父方法(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            数据.threadData.Return = 方法.参数[CS.数字1][valueType.Int] - 1;
            数据.threadData.调用父方法 = true;
        }
        private static void 返回父级(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            数据.threadData.Return = 方法.参数[CS.数字1][valueType.Int];
            数据.threadData.stoploop = 方法.参数[CS.布尔值][valueType.Bool];
        }
        private static void 跳过父级以及后续方法(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            数据.threadData.Return = 方法.参数[CS.数字1][valueType.Int];
            数据.threadData.stoploop = 方法.参数[CS.布尔值][valueType.Bool];
            数据.threadData.跳过后续方法 = true;
        }
        private static void 订阅变量(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            _参数 参数 = 方法.参数[CS.变量1];
            bool 循环 = 方法.参数[CS.循环变量1][valueType.Bool];

            string oldstr = 参数.结果值;
            string newstr = oldstr;
            while (newstr.Equals(oldstr, StringComparison.Ordinal))
            {
                newstr = 参数.结果值;
                方法data.信号.Wait(3);
            }

            if (循环)
            {
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                方法data.循环尾调用 = 0;
                方法data.循环num = 1;
            }
        }
        private static void 预约方法(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法data.第一次执行)
            {
                string 预约方法 = 方法.参数[CS.方法名].结果值;
                int 延后num = 方法.参数[CS.数字1][valueType.Int] - 1;
                数据.预约方法s[预约方法] = (方法, 延后num);
                方法data.第一次执行 = false;
                方法data.循环num = 0;
            }
            else
            {
                bool 循环 = 方法.参数[CS.循环变量1][valueType.Bool];
                if (循环)
                    方法data.循环num = int.MaxValue;
                else
                    方法data.循环num = 1;
                方法data.第一次执行 = true;
            }
            方法data.循环尾调用 = 0;
        }
        private static void 时间筛查(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            int 等待时间 = 方法.参数[CS.时间][valueType.Int];
            bool 起点 = 方法.参数[CS.布尔值][valueType.Bool];
            if (起点)
                数据.时间筛查 = 时间戳;
            else
            {
                if ((时间戳 - 数据.时间筛查) > 等待时间)
                    方法data.循环num = 1;
            }
        }
        private static void 时间拦截(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            int 等待时间 = 方法.参数[CS.时间][valueType.Int];
            bool 取反 = 方法.参数[CS.布尔值2][valueType.Bool];
            bool 重置 = 方法.参数[CS.布尔值3][valueType.Bool];

            Stopwatch 计时器 = 数据.时间分割器.计时器;
            if (重置)
            {
                数据.时间分割器.偏移量 = 0;
                计时器.Restart();
            }

            long 实际等待;
            if (取反)
                实际等待 = 等待时间 + 计时器.ElapsedMilliseconds - 数据.时间分割器.偏移量;
            else
                实际等待 = 等待时间 - 计时器.ElapsedMilliseconds + 数据.时间分割器.偏移量;

            方法data.信号.Wait(实际等待);
            计时器.Restart();

            bool 负时差累计 = 方法.参数[CS.布尔值][valueType.Bool];
            if (负时差累计 && 实际等待 < 0)
                数据.时间分割器.偏移量 += 实际等待;
            else if (!负时差累计)
                数据.时间分割器.偏移量 = 0;
        }
        private static void 异步方法(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            MoyuThreadPool.Post(() =>
            {
                TryCatch(() =>
                {
                    数据.AsyncDatas.TryAdd(方法, new(数据, 0, true, 方法));
                    方法data.循环num = 1;
                    执行方法s(数据, 步骤, 方法.子, 方法, 方法data);
                }, () => 数据.AsyncDatas[方法].ActionEnd = true);
            });
        }
        private static void 时间计划(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            double 当前时间 = 时间戳;
            double 时间差 = 当前时间 - 方法data.时间;
            string 计算公式 = 时间差.ToString() + 方法.参数[CS.代码].值;
            Action action = () =>
            {
                方法data.循环num = 1;
                方法data.时间 = 时间戳;
            };
            if (方法data.时间 == default)
            {
                if (方法.参数[CS.布尔值2][valueType.Bool])
                {
                    action();
                    return;
                }
                else
                    方法data.时间 = 时间戳;
                计算公式 = "0";
            }
            if (计算公式.求值() == "1")
                action();
            else if (方法.参数[CS.布尔值].结果值 == "1")
                方法data.时间 = 时间戳;
        }
        private static void 定时b(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            DateTime 定时 = 方法.参数[CS.时间].Time;
            自旋(() =>
            {
                DateTime time = DateTime.Now;
                方法data.信号.Wait(0);
                return time > 定时;
            });
            方法data.循环num = 1;
        }
        private static void 定时a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            List<int> 时分 = new(方法.参数[CS.时分].值.Split(':').Select(x => int.Parse(x)));
            自旋(() =>
            {
                DateTime time = DateTime.Now;
                方法data.信号.Wait(0);
                return time.Hour == 时分[0] && time.Minute == 时分[1];
            });
            方法data.循环num = 1;
        }
        private static void 截图(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            var frame = 截屏.图片[0, imageType.Mat];
            frame = new Mat(frame, 方法.参数[CS.区域].区域opencvRect);
            Bitmap 图片 = frame.ToBitmap();
            方法.参数[CS.变量1].值.覆盖图片(图片);
        }
        private static void 切换窗口(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            int 句柄 = 方法.参数[CS.数字1][valueType.Int];
            if (句柄 == 0)
            {
                按键(数据, 方法data, Keys.LMenu, true);
                方法data.信号.Wait(1);
                按键(数据, 方法data, Keys.Tab, true);
                方法data.信号.Wait(10);
                按键(数据, 方法data, Keys.Tab, false);
                方法data.信号.Wait(1);
                按键(数据, 方法data, Keys.LMenu, false);
            }
            else
                Win32.SetForegroundWindow(句柄);
        }
        private static void 重排步骤并执行(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 字符串 = 方法.参数[CS.文本1].结果值;
            string[] 顺序stg = 字符串.Split(',');
            var 顺序int = 顺序stg.Select(x => int.Parse(x) - 1);
            数据.Steps = new(顺序int);
            数据.threadData.Return = 20;
        }
        private static void 屏蔽步骤a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            int 步骤int = 方法.参数[CS.数字1][valueType.Int] - 1;
            double 屏蔽时长 = 方法.参数[CS.时间][valueType.Double];
            数据.屏蔽步骤[步骤int] = 时间戳 + 屏蔽时长;
        }
        private static void 屏蔽步骤(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            int 步骤int = 方法.参数[CS.数字1][valueType.Int] - 1;
            bool 解除屏蔽 = 方法.参数[CS.布尔值][valueType.Bool];

            if (解除屏蔽)
                数据.屏蔽步骤.Remove(步骤int);
            else
                数据.屏蔽步骤[步骤int] = double.MaxValue;
        }
        private static void 读取文本文件(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = System.IO.File.ReadAllText(方法.参数[CS.变量1].变量值);
            方法.参数[CS.变量2].值.赋值(内容);
        }
        private static void 获取文字位置(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = 方法.参数[CS.变量1].变量值;
            int 匹配第n个 = 方法.参数[CS.数字1][valueType.Int] - 1;
            string 匹配文字 = 方法.参数[CS.文本1].结果值;
            int 匹配文字Length = 匹配文字.Length;
            string[] 分割文本 = 内容.Split(匹配文字);
            if (匹配第n个 == -1)
                匹配第n个 = 分割文本.Length - 2;
            string new内容 = "";
            int 位置 = 0;
            for (int index = 0; index < 分割文本.Length; index++)
            {
                if (index == 匹配第n个)
                {
                    位置 = 位置 + 分割文本[index].Length;
                    break;
                }
                else
                {
                    位置 = 位置 + 分割文本[index].Length + 匹配文字Length;
                }
            }
            方法.参数[CS.变量2].值.赋值(位置.ToString());
        }
        private static void 删除文字(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = 方法.参数[CS.变量1].变量值;
            int 删除第n个 = 方法.参数[CS.数字1][valueType.Int] - 1;
            string 删除文字 = 方法.参数[CS.文本1].结果值;
            if (删除第n个 == -1)
            {
                string newresults = 内容.Replace(删除文字, "");
                方法.参数[CS.变量2].值.赋值(newresults);
            }
            else
            {
                string[] 分割文本 = 内容.Split(删除文字);
                string new内容 = "";
                for (int index = 0; index < 分割文本.Length; index++)
                {
                    if (index < 分割文本.Length - 1)
                        if (index == 删除第n个)
                            new内容 = new内容 + 分割文本[index];
                        else
                            new内容 = new内容 + 分割文本[index] + 删除文字;
                    else
                        new内容 = new内容 + 分割文本[index];
                }
                方法.参数[CS.变量2].值.赋值(new内容);
            }
        }
        private static void 插入文字(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = 方法.参数[CS.变量1].变量值;
            string 插入文字 = 方法.参数[CS.变量2].结果值;
            int 插入位置 = 方法.参数[CS.数字1][valueType.Int];
            内容 = 内容.Insert(插入位置, 插入文字);
            方法.参数[CS.变量3].值.赋值(内容);
        }
        private static void 替换文字(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = 方法.参数[CS.变量1].变量值;
            string 旧文字 = 方法.参数[CS.文本1].结果值;
            int 替换第n个 = 方法.参数[CS.数字1][valueType.Int] - 1;
            if (替换第n个 == -1)
            {
                string newresults = 内容.Replace(旧文字, 方法.参数[CS.文本2].结果值);
                方法.参数[CS.变量2].值.赋值(newresults);
            }
            else
            {
                string[] 分割文本 = 内容.Split(旧文字);
                string new内容 = "";
                for (int index = 0; index < 分割文本.Length; index++)
                {
                    if (index < 分割文本.Length - 1)
                        if (index == 替换第n个)
                            new内容 = new内容 + 分割文本[index] + 方法.参数[CS.文本2].结果值;
                        else
                            new内容 = new内容 + 分割文本[index] + 旧文字;
                    else
                        new内容 = new内容 + 分割文本[index];
                }
                方法.参数[CS.变量2].值.赋值(new内容);
            }
        }
        private static void 截取文字(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = 方法.参数[CS.变量1].变量值;
            int star = 方法.参数[CS.数字1][valueType.Int];
            int end = 方法.参数[CS.数字2][valueType.Int];
            string newresults = 内容.Substring(star, end);
            方法.参数[CS.变量2].值.赋值(newresults);
        }
        private static void 包含文字(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = 方法.参数[CS.变量1].变量值;
            if (内容.Contains(方法.参数[CS.文本1].值))
                方法data.循环num = 1;
        }
        private static void 获取剪切板内容(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            var 内容 = Clipboard.GetDataObject();
            if (内容.GetFormats().Contains(DataFormats.Bitmap))
            {
                Bitmap 图 = (Bitmap)((Bitmap)内容.GetData(DataFormats.Bitmap)).Clone();
                方法.参数[CS.变量1].值.覆盖图片(图);
            }
            else if (内容.GetFormats().Contains(DataFormats.Text))
            {
                方法.参数[CS.变量1].值.赋值((string)内容.GetData(DataFormats.Text));
            }
            else
            {
                MoyuControl.Msgbox("剪切板内容错误");
            }
        }
        private static void 遍历读取(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 数组名 = 方法.参数[CS.变量1].值;
            string 数组数据 = 数组名.求值();
            string[] 数组 = 数组数据.Split(',');
            int 长度 = 0;
            if (!(数组.Length == 1 && 数组[0] == ""))
                长度 = 数组.Length;
            string 索引变量 = 方法.参数[CS.变量2].值;
            MoyuControl.MsgboxThrow(!数据库.变量.ContainsKey(索引变量), "遍历数组的索引必须是变量");

            int 索引 = int.Parse(索引变量.求值());

            if (!方法data.第一次执行)
                索引变量.赋值((++索引).ToString());
            else
                方法data.第一次执行 = false;

            if (索引 >= 长度)
            {
                _ = 方法.参数[CS.代码].结果值;
                索引 = int.Parse(索引变量.求值());
            }
            if (索引 < 长度)
            {
                string 被赋值变量 = 方法.参数[CS.变量3].值;
                var result = 被赋值变量.提取索引();
                if (result.索引 == -1)
                    被赋值变量.赋值(数组[索引]);
                else
                    被赋值变量.赋值(result.索引, 数组[索引]);
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }
        private static void 遍历写入(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {


            string 数组名 = 方法.参数[CS.变量1].值;
            string 数组数据 = 数组名.求值();
            string[] 数组 = 数组数据.Split(',');
            int 长度 = 0;
            if (!(数组.Length == 1 && 数组[0] == ""))
                长度 = 数组.Length;
            string 索引变量名 = 方法.参数[CS.变量2].值;
            MoyuControl.MsgboxThrow(!数据库.变量.ContainsKey(索引变量名), "遍历数组的索引必须是变量");

            int 索引 = int.Parse(索引变量名.求值());

            if (!方法data.第一次执行)
                索引变量名.赋值((++索引).ToString());
            else
                方法data.第一次执行 = false;

            if (索引 >= 长度)
            {
                _ = 方法.参数[CS.代码].结果值;
                索引 = int.Parse(索引变量名.求值());
            }
            if (索引 < 长度)
            {
                string 写入数据 = 方法.参数[CS.变量3].结果值;
                数组名.赋值(索引, 写入数据);
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }
        private static void 替换索引(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 新数据 = 方法.参数[CS.变量1].结果值;
            string 数组名 = 方法.参数[CS.变量2].值;
            string 数组数据 = 方法.参数[CS.变量2].结果值;
            string[] 数组 = 数组数据.Split(',');
            int 索引位置 = 方法.参数[CS.数字1][valueType.Int];
            StringBuilder 数组数据2 = new("", (数组.Length) * 10);
            char 逗号 = ',';
            for (int i = 0; i < 数组.Length; i++)
            {
                if (i != 索引位置)
                {
                    数组数据2.Append(数组[i]);
                    数组数据2.Append(逗号);
                }
                else
                {
                    数组数据2.Append(新数据);
                    数组数据2.Append(逗号);
                }
            }
            数组数据2.Remove(数组数据2.Length - 1, 1);
            数组名.赋值(数组数据2.ToString());
        }
        private static void 替换元素(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 删除数据 = 方法.参数[CS.变量1].结果值;
            string 新数据 = 方法.参数[CS.变量2].结果值;
            string 数组名 = 方法.参数[CS.变量3].值;
            string 数组数据 = 方法.参数[CS.变量3].结果值;
            string[] 数组 = 数组数据.Split(',');
            int 替换的位置 = 方法.参数[CS.数字1][valueType.Int];
            StringBuilder 数组数据2 = new("", (数组.Length) * 10);
            char 逗号 = ',';
            int 遇到次数 = 0;
            for (int i = 0; i < 数组.Length; i++)
            {
                if (数组[i] != 删除数据)
                {
                    数组数据2.Append(数组[i]);
                    数组数据2.Append(逗号);
                }
                else
                {
                    if (++遇到次数 == 替换的位置 || 替换的位置 <= 0)
                    {
                        数组数据2.Append(新数据);
                        数组数据2.Append(逗号);
                    }
                    else
                    {
                        数组数据2.Append(数组[i]);
                        数组数据2.Append(逗号);
                    }
                }
            }
            数组数据2.Remove(数组数据2.Length - 1, 1);
            数组名.赋值(数组数据2.ToString());
        }
        private static void 删除索引(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 数组名 = 方法.参数[CS.变量1].值;
            string 数组数据 = 方法.参数[CS.变量1].结果值;
            string[] 数组 = 数组数据.Split(',');
            int 删除索引 = 方法.参数[CS.数字1][valueType.Int];
            StringBuilder 数组数据2 = new("", (数组.Length) * 10);
            char 逗号 = ',';
            for (int i = 0; i < 数组.Length; i++)
            {
                if (i != 删除索引)
                {
                    数组数据2.Append(数组[i]);
                    数组数据2.Append(逗号);
                }
            }
            if (数组数据2.Length != 0)
                数组数据2.Remove(数组数据2.Length - 1, 1);
            数组名.赋值(数组数据2.ToString());
        }
        private static void 删除元素(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 删除数据 = 方法.参数[CS.变量1].结果值;
            string 数组名 = 方法.参数[CS.变量2].值;
            string 数组数据 = 方法.参数[CS.变量2].结果值;
            string[] 数组 = 数组数据.Split(',');
            int 删除的位置 = 方法.参数[CS.数字1][valueType.Int];
            StringBuilder 数组数据2 = new("", (数组.Length) * 10);
            char 逗号 = ',';
            int 遇到次数 = 0;
            for (int i = 0; i < 数组.Length; i++)
            {
                if (数组[i] != 删除数据)
                {
                    数组数据2.Append(数组[i]);
                    数组数据2.Append(逗号);
                }
                else
                {
                    if (++遇到次数 == 删除的位置 || 删除的位置 <= 0)
                    {
                    }
                    else
                    {
                        数组数据2.Append(数组[i]);
                        数组数据2.Append(逗号);
                    }
                }
            }
            数组数据2.Remove(数组数据2.Length - 1, 1);
            数组名.赋值(数组数据2.ToString());
        }
        private static void 插入元素(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 变量数据 = 方法.参数[CS.变量1].结果值;
            string 数组名 = 方法.参数[CS.变量2].值;
            string 数组数据 = 方法.参数[CS.变量2].结果值;
            string[] 数组 = 数组数据.Split(',');
            int 插入位置 = 方法.参数[CS.数字1][valueType.Int];
            StringBuilder 数组数据2 = new("", (数组.Length + 1) * 10);
            char 逗号 = ',';
            for (int i = 0; i < 数组.Length; i++)
            {
                if (i == 插入位置)
                {
                    数组数据2.Append(变量数据);
                    数组数据2.Append(逗号);
                    数组数据2.Append(数组[i]);
                }
                else
                    数组数据2.Append(数组[i]);
                数组数据2.Append(逗号);
            }
            数组数据2.Remove(数组数据2.Length - 1, 1);
            数组名.赋值(数组数据2.ToString());
        }
        private static void 添加元素(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 变量数据 = 方法.参数[CS.变量1].结果值;
            string 数组名 = 方法.参数[CS.变量2].值;
            string 数组数据 = 方法.参数[CS.变量2].结果值;
            数组数据 = 数组数据 + ',' + 变量数据;
            数组名.赋值(数组数据);
        }
        private static void 获取长度(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 变量 = 方法.参数[CS.变量1].值;
            string 数组数据 = 方法.参数[CS.变量2].结果值;
            string[] 数组 = 数组数据.Split(',');
            string 长度;
            if (数组.Length == 1 && 数组[0] == "")
                长度 = "0";
            else
                长度 = 数组.Length.ToString();
            变量.赋值(长度);
        }
        private static void 目标检测(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            MoyuControl.MsgboxThrow(!System.IO.File.Exists(方法.参数[CS.文件].值), "模型文件不存在.");
            摸鱼.目标检测.Run(数据, 步骤, 方法, 方法data);
        }
        private static void 训练(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            //摸鱼.目标检测.训练(方法.参数[CS.变量1].值, 方法.参数[CS.变量2].值, double.Parse(方法.参数[CS.学习率].值),
            //     int.Parse(方法.参数[CS.层数].值), int.Parse(方法.参数[CS.尺寸].值), 数据);
        }
        private static void 暂停其他方案(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string[] 方案组 = 方法.参数[CS.调用方案].值.Split(',');
            if (方案组.Length == 0)
                return;
            bool 全部暂停 = false;
            switch (方案组[0])
            {
                case "全部" or "所有":
                    全部暂停 = true;
                    break;
            }

            if (方法data.第一次执行)
            {
                foreach (var 线程列表item in 线程s.Values)
                    foreach (var 方案组item in 方案组)
                    {
                        if (线程列表item.数据.方案 == 数据.方案)
                            break; //----绕开自己
                        if (全部暂停)
                        {
                            foreach (var item in 线程列表item.数据.方法datas.Values)
                                item.信号.Set(item.信号.Wait);
                            break;
                        }
                        else if (线程列表item.数据.方案.名字 == 方案组item)
                        {
                            foreach (var item in 线程列表item.数据.方法datas.Values)
                                item.信号.Set(item.信号.Wait);
                            //----继续切换到下一个方案名
                        }
                    }
                声音.其他(方法.参数[CS.音源].值, float.Parse(方法.参数[CS.音量].结果值), 多线程: true);
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
                方法data.第一次执行 = false;
            }
            else
            {
                foreach (var 线程列表item in 线程s.Values)
                    foreach (var 方案组item in 方案组)
                    {
                        if (线程列表item.数据.方案 == 数据.方案)
                            break;
                        if (全部暂停)
                        {
                            foreach (var item in 线程列表item.数据.方法datas.Values)
                                item.信号.Set(空);
                        }
                        else if (线程列表item.数据.方案.名字 == 方案组item)
                        {
                            foreach (var item in 线程列表item.数据.方法datas.Values)
                                item.信号.Set(空);
                        }
                    }
                声音.其他("继续.wav", float.Parse(方法.参数[CS.音量].结果值), 多线程: true);
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }

        private static void 复制变量值(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 内容 = 方法.参数[CS.变量1].结果值;
            Clipboard.SetDataObject(内容, true, 20, 30);
        }
        private static void 订阅消息(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 暗号 = 方法.参数[CS.暗号].结果值;
            数据.订阅暗号s.Add(暗号);
            消息s.TryAdd(暗号, new());
            BlockingQueue<string> 队列 = 消息s[暗号];
            方法data.信号 ??= new(false);

            double 时间容差 = 方法.参数[CS.时间][valueType.Double];
            string 新消息 = 消息s[暗号].订阅(方法data.信号, 时间容差);

            方法.参数[CS.消息].值.赋值(新消息);

            if (方法.参数[CS.循环变量1][valueType.Bool])
            {
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                方法data.循环尾调用 = 0;
                方法data.循环num = 1;
            }
        }
        private static void 传播消息(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string 暗号 = 方法.参数[CS.暗号].结果值;
            数据.订阅暗号s.Add(暗号);
            消息s.TryAdd(暗号, new());
            消息s[暗号].传播(方法.参数[CS.消息].结果值);
        }


        private static void 位置回溯(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法data.第一次执行)
            {
                方法data.坐标 = Position;
                方法data.第一次执行 = false;
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                Position = 方法data.坐标;
                方法data.第一次执行 = true;
                方法data.循环num = 0;
                方法data.循环尾调用 = 0;
            }
        }
        private static void 时长统计(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法data.第一次执行)
            {
                方法data.时间 = 时间戳;
                方法data.第一次执行 = false;
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                double 耗时 = 时间戳 - 方法data.时间;
                方法.参数[CS.时间].值.赋值(耗时.ToString());
                方法data.第一次执行 = true;
                方法data.循环num = 0;
                方法data.循环尾调用 = 0;
            }
        }
        private static void 获取时间戳(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            方法.参数[CS.方法返回值].值.赋值(时间戳.ToString());
        }
        private static void 同步调用方案(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            _数据 子数据 = 方法data.私有数据;
            if (子数据 == default)
            {
                string 方案string = 方法.参数[CS.调用方案].值;
                子数据 = 返回方案数据(数据库.方案, 方案string);
                MoyuControl.MsgboxThrow(子数据 == default, "调用方案不存在");
                方法data.私有数据 = 子数据;
            }
            else
            {
                子数据.Steps = new();
                子数据.threadData = new();
                子数据.初始化步骤队列(子数据.方案, 0);
            }

            子数据.被调用 = true;
            核心.执行步骤(子数据, true);
            string 返回结果 = 子数据.threadData.返回值.求值();
            方法.参数[CS.变量1].值.赋值(返回结果);

            if (返回结果 == 方法.参数[CS.方案返回值].值)
                方法data.循环num = 1;

            _数据 返回方案数据(List<_方案> 方案items, string 方案string)
            {
                foreach (var 方案item in 方案items)
                {
                    if (方案item.名字 == 方案string)
                        return new(0, 方案item, 数据.方法datas);
                    else if (方案item.子.Count != 0)
                    {
                        var resul = 返回方案数据(方案item.子, 方案string);
                        if (resul != default)
                            return resul;
                    }
                }
                return default;
            }
        }
        private static void 结束方案(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (数据.被调用)
            {
                数据.threadData.返回值 = 方法.参数[CS.方案返回值].结果值 ?? "0";
                数据.threadData.Return = 99;
                return;
            }
            else
                返回顶级调用堆栈();
        }
        private static void 异步调用方案(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string[] 方案组 = 方法.参数[CS.调用方案].值.Split(',');
            if (方案组.Length > 0)
                递归(数据库.方案);

            void 递归(List<_方案> 方案)
            {
                foreach (var item in 方案)
                {
                    foreach (var itemstr in 方案组)
                        if (item.名字 == itemstr)
                        {
                            if (!线程s.ContainsKey(item))
                                核心.启动(item, null);
                        }
                    if (item.子.Count != 0)
                        递归(item.子);
                }
            }
        }
        private static void 创建标签(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法data.控件 == null)
            {
                方法data.Dwm绑定句柄 = nint.MaxValue;
                var 区域 = 方法.参数[CS.区域].区域rectangle;
                var myform = MoyuControl.Form_穿透_置顶.CreateAsyncShow(方法data, 区域, 刷新间隔: 5);
                方法data.控件 = myform;

                方法data.控件.Invoke(() =>
                {
                    System.Windows.Forms.Label label = new();
                    label.AutoSize = false;
                    label.FlatStyle = FlatStyle.Flat;
                    label.Text = 方法.参数[CS.文本1].结果值;
                    label.TextAlign = ContentAlignment.MiddleCenter;
                    var 背景色 = 方法.参数[CS.背景色].区域s;
                    label.BackColor = Color.FromArgb(背景色[0], 背景色[1], 背景色[2]);
                    var 前景色 = 方法.参数[CS.前景色].区域s;
                    label.ForeColor = Color.FromArgb(前景色[0], 前景色[1], 前景色[2]);
                    string 加粗 = 方法.参数[CS.字体加粗].结果值;
                    label.Font = new Font(方法.参数[CS.字体].值, Single.Parse(方法.参数[CS.字体大小].值), 加粗 == "1" ? FontStyle.Bold : FontStyle.Regular);

                    label.Bounds = 区域;
                    label.Location = new(0, 0);

                    方法data.控件.Controls.Add(label);
                    label.Visible = true;
                    label.BringToFront();
                    方法.参数[CS.文本1].Change(数据.参数事件s, 方法data, newstr => label.Text = newstr, myform);
                });
            }
            else
            {
                方法data.控件.Invoke(() =>
                {
                    if (!方法data.控件.Visible)
                        方法data.控件.Show();
                });
            }


            if (方法data.循环num < 2)
            {
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                方法data.循环num = 0;
                方法data.循环尾调用 = 0;
                方法data.控件.BeginInvoke(方法data.控件.Hide);
            }
        }
        private static void 创建按钮a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法data.控件 == null)
                前景窗口.Send(方法data, () =>
                {
                    System.Windows.Forms.Button button = new();
                    方法data.控件 = button;
                    button.AutoSize = false;
                    方法data.信号 = new(false);
                    button.FlatStyle = FlatStyle.Flat;
                    button.Text = 方法.参数[CS.文本1].结果值;
                    button.TextAlign = ContentAlignment.MiddleCenter;
                    var 背景色 = 方法.参数[CS.背景色].区域s;
                    方法data.控件.BackColor = Color.FromArgb(背景色[0], 背景色[1], 背景色[2]);
                    var 前景色 = 方法.参数[CS.前景色].区域s;
                    方法data.控件.ForeColor = Color.FromArgb(前景色[0], 前景色[1], 前景色[2]);
                    string 加粗 = 方法.参数[CS.字体加粗].结果值;
                    方法data.控件.Font = new Font(方法.参数[CS.字体].值, Single.Parse(方法.参数[CS.字体大小].值), 加粗 == "1" ? FontStyle.Bold : FontStyle.Regular);

                    前景窗口.窗体.Controls.Add(方法data.控件);
                    方法data.控件.Bounds = 方法.参数[CS.区域].区域rectangle;
                    方法data.控件.Visible = true;
                    方法data.控件.BringToFront();
                    方法data.控件.MouseUp += 鼠标松开事件;
                    方法data.控件.Disposed += 注销事件;

                    方法.参数[CS.文本1].Change(数据.参数事件s, 方法data, newstr => 方法data.控件.Text = newstr);
                });
            else
            {
                前景窗口.Send(方法data, () =>
                {
                    if (!方法data.控件.Visible)
                        方法data.控件.Show();
                });
            }

            int 显示时长 = 方法.参数[CS.时长][valueType.Int];
            if (!方法data.信号.Wait(显示时长))
                前景窗口.Post(() => 方法data.控件.Hide());

            void 鼠标松开事件(object? sender, System.Windows.Forms.MouseEventArgs e)
            {
                方法data.循环num = 1;
                方法data.信号.Set();
                方法data.控件.Visible = false;
            }
            void 注销事件(object? sender, EventArgs e)
            {
                System.Windows.Forms.Button button = (System.Windows.Forms.Button)sender;
                button.MouseUp -= 鼠标松开事件;
                button.Disposed -= 注销事件;
            }
        }
        private static void 创建按钮(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法data.控件 == null)
                前景窗口.Send(方法data, () =>
                {
                    System.Windows.Forms.Button button = new();
                    方法data.信号 = new(false);
                    方法data.控件 = button;
                    button.AutoSize = false;
                    button.FlatStyle = FlatStyle.Flat;
                    button.Text = 方法.参数[CS.文本1].结果值;
                    button.TextAlign = ContentAlignment.MiddleCenter;
                    var 背景色 = 方法.参数[CS.背景色].区域s;
                    方法data.控件.BackColor = Color.FromArgb(背景色[0], 背景色[1], 背景色[2]);
                    var 前景色 = 方法.参数[CS.前景色].区域s;
                    方法data.控件.ForeColor = Color.FromArgb(前景色[0], 前景色[1], 前景色[2]);
                    string 加粗 = 方法.参数[CS.字体加粗].结果值;
                    方法data.控件.Font = new Font(方法.参数[CS.字体].值, Single.Parse(方法.参数[CS.字体大小].值), 加粗 == "1" ? FontStyle.Bold : FontStyle.Regular);

                    前景窗口.窗体.Controls.Add(方法data.控件);
                    方法data.控件.Bounds = 方法.参数[CS.区域].区域rectangle;
                    方法data.控件.Visible = true;
                    方法data.控件.BringToFront();
                    方法data.控件.MouseUp += 鼠标松开事件;
                    方法data.控件.Disposed += 注销事件;

                    方法.参数[CS.文本1].Change(数据.参数事件s, 方法data, newstr => 方法data.控件.Text = newstr);
                });
            else
                前景窗口.Post(() => 方法data.控件.Text = 方法.参数[CS.文本1].结果值);

            方法data.循环num = int.MaxValue;
            方法data.循环尾调用 = int.MaxValue;
            方法data.信号.Wait();

            void 鼠标松开事件(object? sender, System.Windows.Forms.MouseEventArgs e)
            {
                方法data.信号.Set();
                方法data.控件.Visible = false;
                MoyuDelay.Star(150);
                方法data.控件.Visible = true;
            }
            void 注销事件(object? sender, EventArgs e)
            {
                System.Windows.Forms.Button button = (System.Windows.Forms.Button)sender;
                button.MouseUp -= 鼠标松开事件;
                button.Disposed -= 注销事件;
            }
        }

        private static void 弹起判断(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (!键盘按键判断(数据, 步骤, 方法, 方法data))
                方法data.循环num = 1;
        }
        private static void 按下判断(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (键盘按键判断(数据, 步骤, 方法, 方法data))
                方法data.循环num = 1;
        }
        private static void 鼠标弹起判断(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (!鼠标按键判断(数据, 步骤, 方法, 方法data))
                方法data.循环num = 1;
        }
        private static void 鼠标按下判断(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (鼠标按键判断(数据, 步骤, 方法, 方法data))
                方法data.循环num = 1;
        }
        public static bool 键盘按键判断(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            if (方法data.按键 == null)
            {
                Dictionary<int, bool> 键组Key = new();
                string[] 键组Str = 方法.参数[CS.键盘按键].值.Split('+');
                foreach (var 键 in 键组Str)
                    if (Keys.TryParse(键, out Keys 按键))
                        键组Key.Add((int)按键, default);
                MoyuControl.MsgboxThrow(键组Key.Count == 0, "按键名称错误");
                方法data.按键 = 键组Key;
            }
            List<int> keys = new(键鼠.钩子.键盘按键s.Select(x => x.Keys));
            return keys.全部按下判断(方法data.按键, true);
        }
        private static bool 鼠标按键判断(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法data.按键 == null)
            {
                Dictionary<int, bool> 键组Key = new();
                string[] 键组Str = 方法.参数[CS.鼠标按键].值.Split('+');
                foreach (var 键 in 键组Str)
                    if (int.TryParse(键, out int 按键))
                        键组Key.Add(按键, default);
                MoyuControl.MsgboxThrow(键组Key.Count == 0, "按键名称错误");
                方法data.按键 = 键组Key;
            }
            List<int> keys = new(键鼠.钩子.鼠标按键s.Select(x => x.Keys));
            return keys.全部按下判断(方法data.按键, true);
        }
        private static void 键盘同步鼠标(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            System.Collections.Generic.Dictionary<int, bool> 键组Key;
            if (方法data.按键 == null)
            {
                键组Key = new();
                方法data.信号 = new(false);
                string[] 键组Str = 方法.参数[CS.鼠标按键].值.Split('+');
                foreach (var 键 in 键组Str)
                    if (int.TryParse(键, out int 按键))
                        键组Key.Add(按键, default);
                MoyuControl.MsgboxThrow(键组Key.Count == 0, "按键名称错误");

                Action<List<int>, bool> 监听方法;
                监听方法 = (keyValues, keydown) =>
                {
                    if (keyValues.全部按下_符合逻辑顺序(键组Key, keydown))
                    {
                        方法data.第一次执行 = false;
                        方法data.信号.Set(空);
                    }
                    else if (!keyValues.全部按下判断(键组Key, keydown))
                    {
                        if (!方法data.第一次执行)
                        {
                            方法data.第一次执行 = true;
                            方法data.信号.Set(空);
                        }
                    }
                };
                键鼠.钩子.鼠标Click += 监听方法;
                方法data.按键 = 键组Key;
                方法data.鼠标事件 = 监听方法;
            }
            同步键盘(数据, 步骤, 方法, 方法data);
        }
        private static void 键盘同步键盘(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            System.Collections.Generic.Dictionary<int, bool> 键组Key;
            if (方法data.按键 == null)
            {
                键组Key = new();
                方法data.信号 = new(false);
                string[] 键组Str = 方法.参数[CS.键盘按键].值.Split('+');
                foreach (var 键 in 键组Str)
                    if (Enum.TryParse(键, out Keys 按键))
                        键组Key.Add((int)按键, default);
                MoyuControl.MsgboxThrow(键组Key.Count == 0, "按键名称错误");

                Action<List<int>, bool> 监听方法;
                监听方法 = (keyValues, keydown) =>
                {
                    if (keyValues.全部按下_符合逻辑顺序(键组Key, keydown))
                    {
                        方法data.第一次执行 = false;
                        方法data.信号.Set(空);
                    }
                    else if (!keyValues.全部按下判断(键组Key, keydown))
                    {
                        if (!方法data.第一次执行)
                        {
                            方法data.第一次执行 = true;
                            方法data.信号.Set(空);
                        }
                    }
                };
                键鼠.钩子.键盘Click += 监听方法;
                方法data.按键 = 键组Key;
                方法data.键盘事件 = 监听方法;
            }
            同步键盘(数据, 步骤, 方法, 方法data);
        }
        private static void 同步键盘(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string 句柄文本 = 方法.参数[CS.窗口句柄].结果值;
            IntPtr 句柄;
            string[] 键组Str2 = 方法.参数[CS.键盘按键2].值.Split('+');
            foreach (var 键 in 键组Str2)
                MoyuControl.MsgboxThrow(!Enum.TryParse(键, out Keys _), 键 + " 按键名称错误");

            if (句柄文本 == "0" || 句柄文本 == "")
                句柄 = default;
            else
                句柄 = IntPtr.Parse(句柄文本);

            等待再次按下:
            方法data.信号.Wait();
            string 逻辑 = 方法data.第一次执行 ? "松开" : "按下";
            switch (逻辑)
            {
                case "按下":
                    继续子方法(方法.子);
                    void 继续子方法(List<_方法> items)
                    {
                        foreach (var item in items)
                        {
                            继续子方法(item.子);
                            if (数据.方法datas.TryGetValue(item, out var value))
                                value.信号?.NotSet(null);
                        }
                    }
                    MoyuThreadPool.Post(() =>
                    {
                        TryCatch(() =>
                        {
                            数据.AsyncDatas.TryAdd(方法, new(数据, 0, true, 方法));
                            方法data.循环num = 方法.参数[CS.数字1][valueType.Int];
                            执行方法s(数据, 步骤, 方法.子, 方法, 方法data);
                        }, () => 数据.AsyncDatas[方法].ActionEnd = true);
                    });
                    foreach (var item in 键组Str2)
                        if (Keys.TryParse(item, out Keys key))
                            按键(数据, 方法data, key, true, 句柄);
                    goto 等待再次按下;
                case "松开":
                    if (方法.参数[CS.布尔值][valueType.Bool])
                    {
                        结束子方法(方法.子);
                        void 结束子方法(List<_方法> items)
                        {
                            foreach (var item in items)
                            {
                                结束子方法(item.子);
                                if (数据.方法datas.TryGetValue(item, out var value))
                                    value.信号?.ExitThread();
                            }
                        }
                    }

                    foreach (var item in 键组Str2)
                        if (Enum.TryParse(item, out Keys key))
                            按键(数据, 方法data, key, false, 句柄);
                    goto 等待再次按下;
            }
        }
        private static void 注册鼠标钩子a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            double 阻塞时长 = 方法.参数[CS.时长][valueType.Double];
            double 剩余时长 = 阻塞时长 - (时间戳 - 方法data.时间);
            bool is按下 = 鼠标钩子_已按下(数据, 步骤, 方法, 方法data);

            //初始化
            if (方法data.时间 == 0)
            {
                方法data.时间 = 时间戳;
                剩余时长 = 阻塞时长 - (时间戳 - 方法data.时间);
            }

            bool is超时 = 剩余时长 < 1;

            if (!is超时 && (is按下 || 方法data.信号.Wait(剩余时长)))
            {
                if (方法data.循环num == 1)
                    方法data.时间 = 0;
                else
                {
                    bool 重新计时 = 方法.参数[CS.布尔值][valueType.Bool];
                    if (重新计时)
                    {
                        方法data.时间 = 时间戳;
                        剩余时长 = 阻塞时长 - (时间戳 - 方法data.时间);
                    }
                }
            }
            //超时
            else
            {
                方法data.循环尾调用 = 0;
                方法data.循环num = 0;
                方法data.时间 = 0;
            }
        }
        private static void 弹起鼠标按键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string[] 键组Str = 方法.参数[CS.鼠标按键].值.Split('+');
            List<int> 键组key = new();
            foreach (var item in 键组Str)
            {
                switch (item)
                {
                    case "513":
                        键组key.Add((int)mouse.MOUSEEVENTF_LEFTUP);
                        break;
                    case "516":
                        键组key.Add((int)mouse.MOUSEEVENTF_RIGHTUP);
                        break;
                    case "519":
                        键组key.Add((int)mouse.MOUSEEVENTF_MIDDLEUP);
                        break;
                    case "1":
                        键组key.Add((int)mouse.MOUSEEVENTF_XUP);
                        break;
                    default:
                        MoyuControl.MsgboxThrow(键组Str.Length == 0, "按键名称错误" + item);
                        break;
                }
            }

            foreach (var key in 键组key)
                Win32.mouse_event(key, 0, 0, 0, 0);
        }
        private static void 按住鼠标按键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string[] 键组Str = 方法.参数[CS.鼠标按键].值.Split('+');
            List<int> 键组key = new();
            foreach (var item in 键组Str)
            {
                switch (item)
                {
                    case "513":
                        键组key.Add((int)mouse.MOUSEEVENTF_LEFTDOWN);
                        break;
                    case "516":
                        键组key.Add((int)mouse.MOUSEEVENTF_RIGHTDOWN);
                        break;
                    case "519":
                        键组key.Add((int)mouse.MOUSEEVENTF_MIDDLEDOWN);
                        break;
                    case "1":
                        键组key.Add((int)mouse.MOUSEEVENTF_XDOWN);
                        break;
                    default:
                        MoyuControl.MsgboxThrow(键组Str.Length == 0, "按键名称错误" + item);
                        break;
                }
            }
            foreach (var key in 键组key)
                Win32.mouse_event(key, 0, 0, 0, 0);
        }
        private static void 注册鼠标钩子(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            if (!鼠标钩子_已按下(数据, 步骤, 方法, 方法data))
                方法data.信号.Wait();
        }
        private static bool 鼠标钩子_已按下(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            System.Collections.Generic.Dictionary<int, bool> 键组Key;
            if (方法data.按键 == null)
            {
                键组Key = new();
                方法data.信号 = new(false);
                string[] 键组Str = 方法.参数[CS.鼠标按键].值.Split('+');
                foreach (var 键 in 键组Str)
                    if (int.TryParse(键, out int 按键))
                        键组Key.Add(按键, default);
                MoyuControl.MsgboxThrow(键组Key.Count == 0, "按键名称错误");

                Action<List<int>, bool> 监听方法;
                监听方法 = (keyValues, keydown) =>
                {
                    if (keyValues.全部按下_符合逻辑顺序(键组Key, keydown))
                    {
                        方法data.信号.Set(空);
                        foreach (var item in 键组Key)
                            键组Key[item.Key] = true;
                    }
                    else if (!keyValues.全部按下判断(键组Key, keydown))
                        foreach (var item in 键组Key)
                            键组Key[item.Key] = false;
                };
                键鼠.钩子.鼠标Click += 监听方法;
                方法data.按键 = 键组Key;
                方法data.鼠标事件 = 监听方法;
            }

            bool 按住状态 = true;
            if (方法.参数[CS.持续触发].结果值 == "1")
            {
                foreach (var 键值 in 方法data.按键)
                    if (键值.Value == false)
                    {
                        按住状态 = false;
                        break;
                    }
            }
            else
                按住状态 = false;


            if (方法.参数[CS.循环变量1][valueType.Bool])
            {
                方法data.循环尾调用 = int.MaxValue;
                方法data.循环num = int.MaxValue;
            }
            else
            {
                方法data.循环尾调用 = 0;
                方法data.循环num = 1;
            }
            return 按住状态;
        }
        private static void 注册键盘钩子a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            double 阻塞时长 = 方法.参数[CS.时长][valueType.Double];
            double 剩余时长 = 阻塞时长 - (时间戳 - 方法data.时间);
            bool is按下 = 键盘钩子_已按下(数据, 步骤, 方法, 方法data);

            //初始化
            if (方法data.时间 == 0)
            {
                方法data.时间 = 时间戳;
                剩余时长 = 阻塞时长 - (时间戳 - 方法data.时间);
            }

            bool is超时 = 剩余时长 < 1;

            if (!is超时 && (is按下 || 方法data.信号.Wait(剩余时长)))
            {
                if (方法data.循环num == 1)
                    方法data.时间 = 0;
                else
                {
                    bool 重新计时 = 方法.参数[CS.布尔值][valueType.Bool];
                    if (重新计时)
                    {
                        方法data.时间 = 时间戳;
                        剩余时长 = 阻塞时长 - (时间戳 - 方法data.时间);
                    }
                }
            }
            //超时
            else
            {
                方法data.循环尾调用 = 0;
                方法data.循环num = 0;
                方法data.时间 = 0;
            }
        }
        private static void 注册键盘钩子(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            if (!键盘钩子_已按下(数据, 步骤, 方法, 方法data))
                方法data.信号.Wait();
        }
        private static bool 键盘钩子_已按下(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            方法data.信号.IsSet = false;
            System.Collections.Generic.Dictionary<int, bool> 键组Key;
            if (方法data.按键 == null)
            {
                键组Key = new();
                方法data.信号 = new(false);
                string[] 键组Str = 方法.参数[CS.键盘按键].值.Split('+');
                foreach (var 键 in 键组Str)
                    if (Enum.TryParse(键, out Keys 按键))
                        键组Key.Add((int)按键, default);
                MoyuControl.MsgboxThrow(键组Key.Count == 0, "按键名称错误");

                Action<List<int>, bool> 监听方法;
                监听方法 = (keyValues, keydown) =>
                {
                    if (keyValues.全部按下_符合逻辑顺序(键组Key, keydown))
                    {
                        方法data.第一次执行 = false;
                        方法data.信号.Set(空);
                    }
                    else if (!keyValues.全部按下判断(键组Key, keydown))
                        方法data.第一次执行 = true;
                };
                键鼠.钩子.键盘Click += 监听方法;
                方法data.按键 = 键组Key;
                方法data.键盘事件 = 监听方法;
            }

            if (方法.参数[CS.循环变量1][valueType.Bool])
            {
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                方法data.循环尾调用 = 0;
                方法data.循环num = 1;
            }

            bool 按住状态 = 方法data.第一次执行 || 方法.参数[CS.持续触发].结果值 == "0" ? false : true;
            return 按住状态;
        }
        private static void 获取窗口句柄(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            System.Drawing.Point 目标坐标 = 方法.参数[CS.坐标].坐标;
            IntPtr 句柄 = Win32.WindowFromPoint(目标坐标.X, 目标坐标.Y);
            方法.参数[CS.窗口句柄].值.赋值(句柄.ToString());
        }
        private static void 获取窗口主句柄(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            System.Drawing.Point 目标坐标 = 方法.参数[CS.坐标].坐标;
            IntPtr 次句柄 = Win32.WindowFromPoint(目标坐标.X, 目标坐标.Y);
            IntPtr 主句柄 = Win32.GetHandleWindowMainHandle(次句柄);
            方法.参数[CS.窗口句柄].值.赋值(主句柄.ToString());
        }
        private static void 获取当前窗口主句柄(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            IntPtr 句柄 = Win32.GetActiveWindowMainHandle();
            方法.参数[CS.窗口句柄].值.赋值(句柄.ToString());
        }
        private static void 获取当前窗口句柄(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            IntPtr 句柄 = Win32.GetForegroundWindow();
            方法.参数[CS.窗口句柄].值.赋值(句柄.ToString());
        }
        private static void 滚轮滑动(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            int 滑动次数 = Convert.ToInt16(方法.参数[CS.单击次数].结果值);
            int 滑动间隔 = Convert.ToInt16(方法.参数[CS.单击间隔].结果值);
            int 滑动步长 = Convert.ToInt16(方法.参数[CS.鼠标滚轮步长].结果值);

            int i = 滑动次数;
            while (i-- > 0)
            {
                Win32.mouse_event(Win32.鼠标滚轮, 0, 0, 滑动步长, 0);
                if (i > 0)
                    方法data.信号.Wait(滑动间隔);
            }
        }
        private static void 跳转并结束(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            数据库.当前步骤 = 数据.方案.步骤[int.Parse(方法.参数[CS.跳转步骤].值) - 1];
            返回顶级调用堆栈();
        }
        private static void 跳转步骤(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            数据.初始化步骤队列(数据.方案, int.Parse(方法.参数[CS.跳转步骤].值) - 1);
            数据.threadData.Return = 20;
        }
        private static void 执行多步骤(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            Queue<int> 旧Steps = new(数据.Steps);
            int[] bzs = 方法.参数[CS.变量1].结果值.Split(',').Select(int.Parse).ToArray();
            StringBuilder 返回值s = new();

            foreach (int bz in bzs)
            {
                数据.Steps.Clear();
                数据.Steps.Enqueue(bz - 1);
                核心.执行步骤(数据, false);

                数据.threadData.Return = 0;
                if (返回值s.Length != 0)
                    返回值s.Append(',');
                返回值s.Append(数据.threadData.返回值);
                数据.threadData.返回值 = null;
            }

            数据.Steps = 旧Steps;

            方法.参数[CS.变量2].值.赋值(返回值s.ToString());
            if (方法.参数[CS.变量3][valueType.Bool])
                方法data.循环num = 1;
        }
        private static void 执行步骤(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            Queue<int> 旧Steps = new(数据.Steps);
            数据.Steps.Clear();
            数据.Steps.Enqueue(方法.参数[CS.数字1][valueType.Int] - 1);
            核心.执行步骤(数据, false);
            数据.Steps = 旧Steps;
            数据.threadData.Return = 0;

            string 返回值 = 数据.threadData.返回值;
            数据.threadData.返回值 = "0";
            if (返回值 == 方法.参数[CS.变量1].结果值)
                方法data.循环num = 1;
        }
        private static void 结束步骤(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            数据.threadData.返回值 = 方法.参数[CS.变量1].结果值 ?? "0";
            数据.threadData.Return = 99;
        }
        private static void 屏蔽(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            int[] 区域 = 方法.参数[CS.屏蔽区域].结果值.Split(',').Select(x => int.Parse(x)).ToArray();
            DateTime 记录时间 = DateTime.Now;
            屏蔽区域[记录时间] = new _屏蔽区域()
            {
                区域 = new Rectangle(区域[0], 区域[1], 区域[2], 区域[3]),
                屏蔽时长 = int.Parse(方法.参数[CS.屏蔽时长].结果值)
            };
        }

        [ThreadStatic]
        private static bool 锁定;
        private static void 屏蔽键鼠(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            锁定 = !锁定;
            BlockInput(锁定);
            方法data.循环num = (锁定 ? 1 : 0);
            方法data.循环尾调用 = int.MaxValue;
        }
        private static void 屏蔽移动(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            键鼠.钩子.共享内存2.数据.鼠标锁 = !键鼠.钩子.共享内存2.数据.鼠标锁;
            键鼠.钩子.共享内存2.访问器.Write(0, ref 键鼠.钩子.共享内存2.数据);
            方法data.循环num = (键鼠.钩子.共享内存2.数据.鼠标锁 ? 1 : 0);
            方法data.循环尾调用 = int.MaxValue;
        }
        private static void 获取鼠标特征码(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (MainWindow.CursorFeatures.Get(out long 当前特征码))
            {
                方法.参数[CS.鼠标特征码1].值.赋值(当前特征码.ToString());
                long 比较值 = long.Parse(方法.参数[CS.鼠标特征码2].结果值);
                if (当前特征码 == 比较值)
                    方法data.循环num = 1;
                else
                    方法data.循环num = 0;
            }
        }
        private static void 代码(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            方法.参数[CS.代码].值.求值();
            方法data.循环num = 1;
        }
        private static void 播放(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            声音.其他(方法.参数[CS.音源].值, float.Parse(方法.参数[CS.音量].结果值), 多线程: true);
        }
        private static void 循环(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string[] 判断结果 = 方法.参数[CS.循环变量1].结果值.Split(',');
            int length = 判断结果.Length;
            int i = 0;

            for (; i < length; i++)
                if (!(判断结果[i] == "1"))
                    break;

            if (i == length)
            {
                方法.参数[CS.代码].值.求值();
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                方法.参数[CS.代码2].值.求值();
                方法data.循环num = 0;
            }
        }
        private static void 限时循环(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            double 时长 = 方法.参数[CS.循环变量1][valueType.Double];
            if (方法data.第一次执行)
            {
                方法data.时间 = 时间戳;
                方法data.第一次执行 = false;
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else if (时间戳 - 方法data.时间 > 时长)
            {
                方法data.循环num = 0;
                方法data.第一次执行 = true;
            }
        }
        private static void 判断(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            string[] 判断结果 = 方法.参数[CS.判断变量].结果值.Split(',');
            int length = 判断结果.Length;
            int i = 0;

            for (; i < length; i++)
                if (!(判断结果[i] == "1"))
                    break;

            if (i == length)
            {
                方法.参数[CS.代码].值.求值();
                方法data.循环num = 1;
            }
            else
                方法.参数[CS.代码2].值.求值();
        }

        private static void 等待(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            double ms = 方法.参数[CS.时长][valueType.Double];
            方法data.信号.Wait(ms);
        }

        private static void 等待_偏态分布(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            double 均值 = 方法.参数[CS.数字1][valueType.Double];
            double 下界 = 方法.参数[CS.数字2][valueType.Double];
            double 上界 = 方法.参数[CS.数字3][valueType.Double];
            double 非均值比例 = 方法.参数[CS.数字4][valueType.Double];

            // 使用Beta分布方案
            double 等待时间 = 生成Beta偏态分布(均值, 下界, 上界, 非均值比例);
            方法data.信号.Wait((int)等待时间);
        }
        /// <summary>
        /// 使用Beta分布实现偏态分布（推荐方案）
        /// </summary>
        private static double 生成Beta偏态分布(double 均值, double 下界, double 上界, double 非均值比例)
        {
            Random 随机 = new Random(Guid.NewGuid().GetHashCode());

            // 根据非均值比例计算Beta分布参数
            // 非均值比例越大，分布越偏
            double 偏态强度 = 非均值比例 * 5 + 1; // 1-6之间

            // 决定偏态方向（基于均值位置）
            double 相对位置 = (均值 - 下界) / (上界 - 下界);
            bool 右偏 = 相对位置 < 0.7; // 如果均值偏左，则右偏

            double alpha, beta;

            if (右偏)
            {
                alpha = 偏态强度;
                beta = 8 - 偏态强度; // 确保alpha < beta 产生右偏
            }
            else
            {
                alpha = 8 - 偏态强度; // 确保alpha > beta 产生左偏
                beta = 偏态强度;
            }

            // 生成Beta分布随机数
            double beta值 = Beta.Sample(随机, alpha, beta);

            // 映射到指定范围
            return 下界 + beta值 * (上界 - 下界);
        }

        private static void 组合键拆解(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string 方法不存在str = "不存在此方法名 " + 方法.名字;
            MoyuControl.MsgboxThrow(!方法.参数.ContainsKey(CS.单击间隔), 方法不存在str);
            int 单击间隔 = int.Parse(方法.参数[CS.单击间隔].结果值);

            MoyuControl.MsgboxThrow(!方法.参数.ContainsKey(CS.单击次数), 方法不存在str);
            if (方法data.第几次循环 == -1)
                方法data.第几次循环 = int.Parse(方法.参数[CS.单击次数].结果值);

            MoyuControl.MsgboxThrow(!方法.参数.ContainsKey(CS.窗口句柄), 方法不存在str);
            string 句柄文本 = 方法.参数[CS.窗口句柄].结果值;
            IntPtr 句柄;
            string[] 键组Str = 方法.名字.Split('+');
            List<Keys> 键组key = new();
            foreach (var item in 键组Str)
                if (Keys.TryParse(item, out Keys key))
                    键组key.Add(key);
                else
                    MoyuControl.MsgboxThrow(键组Str.Length == 0, "按键名称错误" + item);

            if (句柄文本 == "0" || 句柄文本 == "")
                句柄 = default;
            else
                句柄 = IntPtr.Parse(句柄文本);

            if (方法data.第几次循环-- > 0)
            {
                if (方法data.第一次执行)
                {
                    foreach (var item in 键组key)
                        按键(数据, 方法data, item, true, 句柄);
                    方法data.第一次执行 = false;
                }
                else
                {
                    foreach (var item in 键组key)
                        按键(数据, 方法data, item, false, 句柄);
                    方法data.信号.Wait(单击间隔);
                    foreach (var item in 键组key)
                        按键(数据, 方法data, item, true, 句柄);
                }
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                foreach (var item in 键组key)
                    按键(数据, 方法data, item, false, 句柄);
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }
        private static 手柄模拟 手柄;
        private static void 注销手柄(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => 手柄.Dispose();
        private static void 手柄Up键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.Up);
        private static void 手柄Down键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.Down);
        private static void 手柄Left键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.Left);
        private static void 手柄Right键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.Right);
        private static void Start(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.Start);
        private static void 手柄Back键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.Back);
        private static void LS(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.LeftThumb);
        private static void RS(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.RightThumb);
        private static void LB(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.LeftShoulder);
        private static void RB(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.RightShoulder);
        private static void Guide(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.Guide);
        private static void 手柄A键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.A);
        private static void 手柄B键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.B);
        private static void 手柄X键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.X);
        private static void 手柄Y键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360ButtonClick(数据, 步骤, 方法, 方法data, Xbox360Button.Y);
        public static void Xbox360ButtonClick(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data, Xbox360Button key)
        {
            手柄 ??= new();
            int 单击间隔 = int.Parse(方法.参数[CS.单击间隔].结果值);
            if (方法data.第几次循环 == -1)
                方法data.第几次循环 = int.Parse(方法.参数[CS.单击次数].结果值);

            if (方法data.第几次循环-- > 0)
            {
                if (方法data.第一次执行)
                {
                    手柄.ButtonDown(key);
                    方法data.第一次执行 = false;
                }
                else
                {
                    手柄.ButtonUp(key);
                    方法data.信号.Wait(单击间隔);
                    手柄.ButtonDown(key);
                }
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                手柄.ButtonUp(key);
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }
        public static void LT(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            手柄 ??= new();
            int 单击间隔 = int.Parse(方法.参数[CS.单击间隔].结果值);
            byte 按下深度 = (byte)(方法.参数[CS.数字1][valueType.Float] * 255);
            byte 弹起位置 = (byte)(方法.参数[CS.数字2][valueType.Float] * 255);
            if (方法data.第几次循环 == -1)
                方法data.第几次循环 = int.Parse(方法.参数[CS.单击次数].结果值);

            if (方法data.第几次循环-- > 0)
            {
                if (方法data.第一次执行)
                {
                    手柄.xbox360Slider(Xbox360Slider.LeftTrigger, 按下深度);
                    方法data.第一次执行 = false;
                }
                else
                {
                    手柄.xbox360Slider(Xbox360Slider.LeftTrigger, 弹起位置);
                    方法data.信号.Wait(单击间隔);
                    手柄.xbox360Slider(Xbox360Slider.LeftTrigger, 按下深度);
                }
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                手柄.xbox360Slider(Xbox360Slider.LeftTrigger, 弹起位置);
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }
        public static void RT(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            手柄 ??= new();
            int 单击间隔 = int.Parse(方法.参数[CS.单击间隔].结果值);
            byte 按下深度 = (byte)(方法.参数[CS.数字1][valueType.Float] * 255);
            byte 弹起位置 = (byte)(方法.参数[CS.数字2][valueType.Float] * 255);
            if (方法data.第几次循环 == -1)
                方法data.第几次循环 = int.Parse(方法.参数[CS.单击次数].结果值);

            if (方法data.第几次循环-- > 0)
            {
                if (方法data.第一次执行)
                {
                    手柄.xbox360Slider(Xbox360Slider.RightTrigger, 按下深度);
                    方法data.第一次执行 = false;
                }
                else
                {
                    手柄.xbox360Slider(Xbox360Slider.RightTrigger, 弹起位置);
                    方法data.信号.Wait(单击间隔);
                    手柄.xbox360Slider(Xbox360Slider.RightTrigger, 按下深度);
                }
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                手柄.xbox360Slider(Xbox360Slider.RightTrigger, 弹起位置);
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }
        private static void 右摇杆X轴(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360摇杆(数据, 步骤, 方法, 方法data, Xbox360Axis.RightThumbX);
        private static void 右摇杆Y轴(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360摇杆(数据, 步骤, 方法, 方法data, Xbox360Axis.RightThumbY);
        private static void 左摇杆X轴(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360摇杆(数据, 步骤, 方法, 方法data, Xbox360Axis.LeftThumbX);
        private static void 左摇杆Y轴(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => Xbox360摇杆(数据, 步骤, 方法, 方法data, Xbox360Axis.LeftThumbY);
        public static void Xbox360摇杆(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data, Xbox360Axis xbox360Axis)
        {
            手柄 ??= new();
            float 轴位置1float = 方法.参数[CS.数字1][valueType.Float];
            float 轴位置2float = 方法.参数[CS.数字2][valueType.Float];
            //-32768到32767
            轴位置1float = 轴位置1float > 0 ? 轴位置1float * 32767 : 轴位置1float * (-32768);
            轴位置2float = 轴位置2float > 0 ? 轴位置2float * 32767 : 轴位置2float * (-32768);
            short 轴位置1short = (short)轴位置1float;
            short 轴位置2short = (short)轴位置2float;

            if (方法data.第一次执行)
            {
                手柄.xbox360Axis(xbox360Axis, 轴位置1short);
                方法data.第一次执行 = false;
                方法data.循环num = 1;
                方法data.循环尾调用 = 1;
            }
            else
            {
                手柄.xbox360Axis(xbox360Axis, 轴位置2short);
                方法data.第一次执行 = true;
                方法data.循环num = 0;
                方法data.循环尾调用 = 0;
            }
        }
        public static void 按键(_数据 数据, _方法data 方法data, Keys key, bool 按下, IntPtr 句柄 = default)
        {
            if (句柄 == default)
            {
                if (按下)
                {
                    方法data.已按下按键s.Add(key);
                    var bscan = Win32.扫描码get(key);
                    Win32.keybd_event((byte)key, (byte)bscan, 0, 0);
                }
                else
                {
                    var bscan = Win32.扫描码get(key);
                    Win32.keybd_event((byte)key, (byte)bscan, 2, 0);
                    方法data.已按下按键s.Remove(key);
                }
            }
            else
            {
                if (按下)
                {
                    //Win32.SendMessage(句柄, (uint)Send.WM_KEYDOWN, (uint)key, (uint)0 << 31);
                    while (Win32.SendMessageTimeout(句柄, (uint)Send.WM_KEYDOWN, (uint)key, (uint)0 << 31, Win32.等待完成或出错, 3, out _) == IntPtr.Zero)
                        方法data.信号.Wait(0);

                }
                else
                {
                    //Win32.SendMessage(句柄, (uint)Send.WM_KEYUP, (uint)key, (uint)1 << 31);
                    while (Win32.SendMessageTimeout(句柄, (uint)Send.WM_KEYUP, (uint)key, (uint)1 << 31, Win32.等待完成或出错, 3, out _) == IntPtr.Zero)
                        方法data.信号.Wait(0);
                }
            }
        }
        private static void 按住按键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string[] 键组Str = 方法.参数[CS.键盘按键].值.Split('+');
            List<Keys> 键组key = new();
            foreach (var item in 键组Str)
                if (Keys.TryParse(item, out Keys key))
                    键组key.Add(key);
                else
                    MoyuControl.MsgboxThrow(键组Str.Length == 0, "按键名称错误" + item);

            foreach (var key in 键组key)
            {
                方法data.已按下按键s.Add(key);
                var bscan = Win32.扫描码get(key);
                Win32.keybd_event((byte)key, (byte)bscan, 0, 0);
            }
        }
        private static void 弹起按键(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string[] 键组Str = 方法.参数[CS.键盘按键].值.Split('+');
            List<Keys> 键组key = new();
            foreach (var item in 键组Str)
                if (Keys.TryParse(item, out Keys key))
                    键组key.Add(key);
                else
                    MoyuControl.MsgboxThrow(键组Str.Length == 0, "按键名称错误" + item);

            foreach (var key in 键组key)
            {
                var bscan = Win32.扫描码get(key);
                Win32.keybd_event((byte)key, (byte)bscan, 2, 0);
                方法data.已按下按键s.Remove(key);
            }
        }

        public static void SendDown(Keys key)
        {
            INPUT input = new INPUT();
            input.type = SendInputs.INPUT_KEYBOARD;
            input.U.ki.wVk = (ushort)key;
            input.U.ki.wScan = (ushort)Win32.扫描码get(key);
            input.U.ki.time = (int)时间戳;
            input.U.ki.dwExtraInfo = IntPtr.Zero;
            input.U.ki.dwFlags = KEYEVENTF_KEYDOWN;

            SendInput(1, [input], Marshal.SizeOf(input));
        }
        public static void SendUp(Keys key)
        {
            INPUT input = new INPUT();
            input.type = SendInputs.INPUT_KEYBOARD;
            input.U.ki.wVk = (ushort)key;
            input.U.ki.wScan = (ushort)Win32.扫描码get(key);
            input.U.ki.time = (int)时间戳;
            input.U.ki.dwExtraInfo = IntPtr.Zero;
            input.U.ki.dwFlags = KEYEVENTF_KEYUP;

            SendInput(1, [input], Marshal.SizeOf(input));
        }

        private static void 获取位置(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            System.Drawing.Point mouse = System.Windows.Forms.Control.MousePosition;
            方法.参数[CS.鼠标位置].值.赋值($"{mouse.X},{mouse.Y}");
        }
        private static void 相对移动2(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            System.Drawing.Point 目标坐标 = 方法.参数[CS.相对距离].坐标;
            float 当前X = 0;
            float 当前Y = 0;
            int 移动时间 = int.Parse(方法.参数[CS.移动时间].值);
            float 间隔 = 1000f / 方法.参数[CS.时间][valueType.Int];

            // 误差累积和补偿
            float x累积误差 = 0;
            float y累积误差 = 0;
            const float 误差阈值 = 1.0f; // 固定阈值，达到1像素就补偿

            Win32.禁用鼠标加速();
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            while (stopwatch.ElapsedMilliseconds < 移动时间)
            {
                float 剩余时间 = 移动时间 - stopwatch.ElapsedMilliseconds;
                float 剩余x差 = 目标坐标.X - 当前X;
                float 剩余y差 = 目标坐标.Y - 当前Y;

                // 计算剩余步数，确保至少1步
                float 剩余步数 = Math.Max(剩余时间 / 间隔, 1);

                // 计算理论移动量（包含小数）
                float dx = 剩余x差 / 剩余步数;
                float dy = 剩余y差 / 剩余步数;

                // 累积误差
                x累积误差 += dx;
                y累积误差 += dy;

                // 提取整数部分作为实际移动
                int intdx = (int)x累积误差;
                int intdy = (int)y累积误差;

                // 保留小数部分继续累积
                x累积误差 -= intdx;
                y累积误差 -= intdy;

                // 执行移动
                if (intdx != 0 || intdy != 0)
                {
                    当前X += intdx;
                    当前Y += intdy;
                    Win32.mouse_event(MOUSEEVENTF_MOVE, intdx, intdy, 0, 0);
                }

                // 等待下一帧
                if (剩余时间 > 间隔)
                {
                    方法data.信号.Wait((int)间隔);
                }
            }

            // 最终位置校正（处理累积的微小误差）
            int 最终x差 = 目标坐标.X - (int)当前X;
            int 最终y差 = 目标坐标.Y - (int)当前Y;
            if (最终x差 != 0 || 最终y差 != 0)
                Win32.mouse_event(MOUSEEVENTF_MOVE, 最终x差, 最终y差, 0, 0);
            Win32.启用鼠标加速();
        }

        private static void 画圆(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            float 半径 = 方法.参数[CS.半径][valueType.Float];
            double 圆周长 = 2.0 * Math.PI * 半径;
            double 总长度 = 方法.参数[CS.长度][valueType.Double];
            if (总长度 == 0)
                总长度 = 圆周长;
            int 时长 = 方法.参数[CS.时长][valueType.Int];
            float 总耗时 = 时长 == 0 ? 500 : 时长;
            int 单步耗时 = 方法.参数[CS.数字2][valueType.Int]; ;
            double 线段数量 = Math.Abs(总耗时 / 单步耗时);
            double 线段长度 = 总长度 / (double)线段数量;

            // 计算出每个线段应该旋转的角度  
            double 角度步长 = (Math.PI * 2.0) * (总长度 / 圆周长) / 线段数量;

            double 当前角度 = Math.PI * ((方法.参数[CS.角度][valueType.Float] / 360) * 2);
            System.Drawing.Point 初始鼠标位置 = System.Windows.Forms.Cursor.Position;
            System.Drawing.Point 圆心 = new System.Drawing.Point((int)(初始鼠标位置.X - 半径 * Math.Cos(当前角度)), (int)(初始鼠标位置.Y - 半径 * Math.Sin(当前角度)));

            double 上次记录 = 时间戳;
            switch (方法.参数[CS.数字1][valueType.Int])
            {
                case 1: // 顺时针     
                    for (int i = 0; i <= 线段数量; i++)
                    {
                        // 计算出下一个点的位置  
                        Point 相对坐标 = new Point((int)(半径 * Math.Cos(当前角度)), (int)(半径 * Math.Sin(当前角度)));
                        Point 绝对坐标 = new Point(圆心.X + 相对坐标.X, 圆心.Y + 相对坐标.Y);

                        // 设置鼠标位置  
                        System.Windows.Forms.Cursor.Position = 绝对坐标;

                        // 暂停一段时间，以控制鼠标移动速度  
                        自旋2();

                        // 计算出下一个点的角度  
                        当前角度 += 角度步长;
                    }
                    break;
                default: // 逆时针
                    for (int i = 0; i <= 线段数量; i++)
                    {
                        // 计算出下一个点的位置  
                        Point 相对坐标 = new Point((int)(半径 * Math.Cos(当前角度)), (int)(半径 * Math.Sin(当前角度)));
                        Point 绝对坐标 = new Point(圆心.X + 相对坐标.X, 圆心.Y + 相对坐标.Y);

                        // 设置鼠标位置  
                        System.Windows.Forms.Cursor.Position = 绝对坐标;

                        // 暂停一段时间，以控制鼠标移动速度  
                        自旋2();

                        // 计算出下一个点的角度  
                        当前角度 -= 角度步长;
                    }
                    break;
            }

            void 自旋2()
            {
                方法data.信号.Wait(0);
                自旋(() =>
                {
                    double 最新时间 = 时间戳;
                    if (最新时间 > 上次记录)
                    {
                        上次记录 += 单步耗时;
                        return true;
                    }
                    else
                        return false;
                });
            }
        }
        private static void 相对移动1(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            System.Drawing.Point mouse = System.Windows.Forms.Control.MousePosition;
            System.Drawing.Point 目标坐标 = 方法.参数[CS.相对坐标].坐标 + (System.Drawing.Size)方法.参数[CS.相对距离].坐标;
            移动鼠标(mouse, 目标坐标, int.Parse(方法.参数[CS.移动时间].值), 方法.参数[CS.时间][valueType.Int], 数据, 方法data);
        }
        private static void 相对移动3(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            System.Drawing.Point mouse = System.Windows.Forms.Control.MousePosition;
            System.Drawing.Point 目标坐标 = mouse + (System.Drawing.Size)方法.参数[CS.相对距离].坐标;
            移动鼠标(mouse, 目标坐标, int.Parse(方法.参数[CS.移动时间].值), 方法.参数[CS.时间][valueType.Int], 数据, 方法data);
        }
        private static void 直线移动(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            移动鼠标(System.Windows.Forms.Control.MousePosition, 方法.参数[CS.坐标].坐标,
                方法.参数[CS.移动时间][valueType.Int], 方法.参数[CS.时间][valueType.Int], 数据, 方法data);
        }
        private static void 人类鼠标移动(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            var 人类移动 = new 鼠标轨迹模拟();
            Point 起点 = System.Windows.Forms.Control.MousePosition;
            Point 终点 = 方法.参数[CS.坐标].坐标;
            int 随机定位半径 = 方法.参数[CS.半径][valueType.Int];
            int 移动时间 = 方法.参数[CS.移动时间][valueType.Int];
            人类移动.人类方式移动(起点, 终点, 移动时间, 随机定位半径);
        }
        private static void 移动鼠标(System.Drawing.Point 起点, System.Drawing.Point 终点, int 总时长, int 帧率, _数据 数据, _方法data 方法data)
        {
            float 起点X = 起点.X;
            float 起点Y = 起点.Y;
            float 终点X = 终点.X;
            float 终点Y = 终点.Y;
            float 间隔 = 1000f / 帧率;
            int 移动次数 = (总时长 * 1F / 间隔).round();
            float X偏移量 = (终点X - 起点X) / 移动次数;
            float Y偏移量 = (终点Y - 起点Y) / 移动次数;
            Queue<float> X坐标 = new Queue<float>();
            Queue<float> Y坐标 = new Queue<float>();
            for (float i = 0; i < 移动次数; i++)
            {
                X坐标.Enqueue(起点X += X偏移量);
                Y坐标.Enqueue(起点Y += Y偏移量);
            }
            间隔--;
            while (X坐标.TryDequeue(out float x) && Y坐标.TryDequeue(out float y))
            {
                Position = new System.Drawing.Point((int)Math.Round(x), (int)Math.Round(y));
                方法data.信号.Wait(间隔);
            }
            if (移动次数 < 1)
                Position = 终点;
        }

        private static void 原地右击(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法.参数[CS.窗口句柄].结果值 == "0")
                单击(数据, 方法, 方法data, (int)mouse.MOUSEEVENTF_RIGHTDOWN, (int)mouse.MOUSEEVENTF_RIGHTUP, false, 0);
            else
                后台单击(数据, 方法, 方法data, (uint)Send.WM_RBUTTONDOWN, false, (uint)Send.WM_RBUTTONUP);
        }
        private static void 原地左击(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法.参数[CS.窗口句柄].结果值 == "0")
                单击(数据, 方法, 方法data, (int)mouse.MOUSEEVENTF_LEFTDOWN, (int)mouse.MOUSEEVENTF_LEFTUP, false, 0);
            else
                后台单击(数据, 方法, 方法data, (uint)Send.WM_LBUTTONDOWN, false, (uint)Send.WM_LBUTTONUP);
        }
        private static void 左击(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法.参数[CS.窗口句柄].结果值 == "0")
                单击(数据, 方法, 方法data, (int)mouse.MOUSEEVENTF_LEFTDOWN, (int)mouse.MOUSEEVENTF_LEFTUP, true, 0);
            else
                后台单击(数据, 方法, 方法data, (uint)Send.WM_LBUTTONDOWN, true, (uint)Send.WM_LBUTTONUP);
        }
        private static void 左击a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            int 前摇 = 方法.参数[CS.时长][valueType.Int];
            if (方法.参数[CS.窗口句柄].结果值 == "0")
                单击(数据, 方法, 方法data, (int)mouse.MOUSEEVENTF_LEFTDOWN, (int)mouse.MOUSEEVENTF_LEFTUP, true, 前摇);
            else
                后台单击(数据, 方法, 方法data, (uint)Send.WM_LBUTTONDOWN, true, (uint)Send.WM_LBUTTONUP);
        }
        private static void 右击(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            if (方法.参数[CS.窗口句柄].结果值 == "0")
                单击(数据, 方法, 方法data, (int)mouse.MOUSEEVENTF_RIGHTDOWN, (int)mouse.MOUSEEVENTF_RIGHTUP, true, 0);
            else
                后台单击(数据, 方法, 方法data, (uint)Send.WM_RBUTTONDOWN, true, (uint)Send.WM_RBUTTONUP);
        }
        private static void 右击a(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

            int 前摇 = 方法.参数[CS.时长][valueType.Int];
            if (方法.参数[CS.窗口句柄].结果值 == "0")
                单击(数据, 方法, 方法data, (int)mouse.MOUSEEVENTF_RIGHTDOWN, (int)mouse.MOUSEEVENTF_RIGHTUP, true, 前摇);
            else
                后台单击(数据, 方法, 方法data, (uint)Send.WM_RBUTTONDOWN, true, (uint)Send.WM_RBUTTONUP);
        }

        private static void 后台单击(_数据 数据, _方法 方法, _方法data 方法data, uint 按下, bool 移动鼠标, uint 弹起)
        {
            System.Drawing.Point 目标坐标;
            if (移动鼠标)
                目标坐标 = 方法.参数[CS.坐标].坐标;
            else
                目标坐标 = Position;
            IntPtr 句柄 = IntPtr.Parse(方法.参数[CS.窗口句柄].结果值);
            //窗口坐标转屏幕坐标
            Win32.GetWindowRect(句柄, out Win32.RECT 窗口坐标);
            int X = 目标坐标.X - 窗口坐标.Left, Y = 目标坐标.Y - 窗口坐标.Top;
            uint lParam = ((uint)((Y << 16) | X));

            if (方法data.第几次循环-- > 0)
            {
                int 单击间隔 = Convert.ToInt16(方法.参数[CS.单击间隔].结果值);
                if (方法data.第几次循环 == -1)
                    方法data.第几次循环 = int.Parse(方法.参数[CS.单击次数].结果值);

                if (方法data.第一次执行)
                {
                    Win32.SendMessage(句柄, 按下, 0, lParam);
                    方法data.第一次执行 = false;
                }
                else
                {
                    Win32.PostMessage(句柄, 弹起, 0, lParam);
                    方法data.信号.Wait(单击间隔);
                    Win32.SendMessage(句柄, 按下, 0, lParam);
                }
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                Win32.PostMessage(句柄, 弹起, 0, lParam);
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }
        private static void 单击(_数据 数据, _方法 方法, _方法data 方法data, int 按下, int 弹起, bool 移动鼠标, int 前摇)
        {
            int 单击间隔 = Convert.ToInt16(方法.参数[CS.单击间隔].结果值);
            if (方法data.第几次循环 == -1)
                方法data.第几次循环 = int.Parse(方法.参数[CS.单击次数].结果值);

            if (方法data.第几次循环-- > 0)
            {
                if (移动鼠标)
                    Position = 方法.参数[CS.坐标].坐标;
                方法data.信号.Wait(前摇);
                if (方法data.第一次执行)
                {
                    Win32.mouse_event(按下, 0, 0, 0, 0);
                    方法data.第一次执行 = false;
                }
                else
                {
                    Win32.mouse_event(弹起, 0, 0, 0, 0);
                    方法data.信号.Wait(单击间隔);
                    Win32.mouse_event(按下, 0, 0, 0, 0);
                }
                方法data.循环num = int.MaxValue;
                方法data.循环尾调用 = int.MaxValue;
            }
            else
            {
                Win32.mouse_event(弹起, 0, 0, 0, 0);
                方法data.循环num = 0;
                方法data.第一次执行 = true;
                方法data.循环尾调用 = 0;
            }
        }
        private static void 取色(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            bool 取反 = 方法.参数[CS.布尔值].结果值 == "1";
            float 相似度 = float.Parse(方法.参数[CS.相似度1].结果值);
            List<MoyuBitmap> bitmaps = 方法.参数[CS.图片1].值.取图();
            List<颜色> 色组 = new();
            for (int i = 0; i < bitmaps.Count; i++)
            {
                颜色 j = bitmaps[i].Mat.GetPixel(0, 0);
                色组.Add(new 颜色(j.R, j.G, j.B));
            }
            bitmaps = null;

            int[] 取色区域 = 方法.参数[CS.区域].区域s;

            颜色 区域颜色 = 截屏.取色(取色区域[0], 取色区域[1]);

            float 匹配度 = 0;
            for (int i = 0; i < 色组.Count; i++)
            {
                匹配度 = 1 - 区域颜色.相似度(色组[i]);
                bool 匹配 = 匹配度 >= 相似度;
                if (匹配 && !取反)
                {
                    方法data.循环num = 1;
                    break;
                }
                else if (!匹配 && 取反)
                {
                    方法data.循环num = 1;
                    break;
                }
                else
                    方法data.循环num = 0;
            }
            色组.Clear();
        }
        private static void 特征匹配(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => 图形处理.特征匹配(数据, 步骤, 方法, 方法data);
        private static void 找色块(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => 图形处理.找色块(数据, 步骤, 方法, 方法data);
        private static void SVM二分类训练(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            List<Mat> 正样本 = 方法.参数[CS.图片1].值.取图().Select(item => item.Mat).ToList();
            List<Mat> 负样本 = 方法.参数[CS.图片2].值.取图().Select(item => item.Mat).ToList();

        }
        private static void SVM二分类检测(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {

        }
        private static void 图片录制拼接(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => 图形处理.图片录制拼接(数据, 步骤, 方法, 方法data);
        private static void 误差验证(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            float 相似度 = float.Parse(方法.参数[CS.相似度1].结果值);
            double 数值1 = 方法.参数[CS.变量1][valueType.Double],
                   数值2 = 方法.参数[CS.变量2][valueType.Double];
            double 差值 = Math.Abs(数值1 - 数值2);
            if (差值 <= (1 - 相似度) * Math.Max(Math.Abs(数值1), Math.Abs(数值2)))
                方法data.循环num = 1;
            else
                方法data.循环num = 0;
        }
        private static void 距离计算(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            string 表达式1 = 方法.参数[CS.代码].值;
            Point 坐标1 = 方法.参数[CS.变量1].坐标,
                  坐标2 = 方法.参数[CS.变量2].坐标;
            double dx = 坐标2.X - 坐标1.X;
            double dy = 坐标2.Y - 坐标1.Y;
            var 距离 = Math.Sqrt(dx * dx + dy * dy);
            string 表达式2 = 距离 + 表达式1;

            if (表达式2.求值() == "1")
                方法data.循环num = 1;
            else
                方法data.循环num = 0;
        }
        private static void 找单色(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data)
        {
            图形处理.找单色(数据, 步骤, 方法, 方法data);
        }
        private static void 模板找图(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => 图形处理.模板找图(数据, 步骤, 方法, 方法data);
        private static void 变化监控(_数据 数据, _步骤 步骤, _方法 方法, _方法data 方法data) => 图形处理.变化监控(数据, 步骤, 方法, 方法data);







    }
}
